<!DOCTYPE html>
<html lang="zh-cn">
  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="author" content="Zhou Wei <zromyk@163.com>">
  <title>MySQL 数据库</title>
  <link rel="shortcut icon" href="/favicon.ico">
  <link rel="stylesheet" href="/style/html/pure.css">
  <link rel="stylesheet" href="/style/html/main.css">
  <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
  <!-- <link rel="stylesheet" href="https://apps.bdimg.com/libs/highlight.js/9.1.0/styles/default.min.css"> -->
<link rel="stylesheet" href="/style/article/highlight/default.min.css">
<link rel="stylesheet" href="/style/article/pell-1.0.6/dist/pell.css">

</head>
<body>
  <div id="menu-background"></div>
  <div id="menu">
    <div class="pure-menu pure-menu-horizontal">
  <ul class="pure-menu-list block-middle">
    <li class="pure-menu-item">
  <a class="pure-menu-heading" href="/index.html">ZROMYK</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/index.html">主页</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/archive/index.html">归档</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/download/index.html">下载</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/feedback/index.html">反馈</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/about/index.html">关于我</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="https://github.com/zromyk"><i class="fa fa-github" style="font-size:32px"></i></a>
</li>

  </ul>
</div>

  </div>
  <div id="layout">
    <div class="content">
      <div id="nav">
    <div id="navigation" class="navigation">
  <ul class="pure-menu-list">
    <li class="pure-menu-item">
  <a class="pure-menu-link nav1" onclick="animateByNav()" href="#mysql">第一部分 MySQL 基础知识</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#1-mysql-sql-2">第1 章 MySQL 和SQL 入门 2</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#11-mysql-2">1.1 MySQL 的用途 2</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#12-4">1.2 示例数据库 4</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#121-5">1.2.1 “美国历史研究会”场景 5</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#122-7">1.2.2 考试记分项目 7</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#123-7">1.2.3 关于示例数据库的说明 7</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#13-7">1.3 数据库基本术语 7</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#131-8">1.3.1 数据库的组织结构 8</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#132-10">1.3.2 数据库查询语言 10</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#133-mysql-10">1.3.3 MySQL 的体系结构 10</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#14-mysql-11">1.4 MySQL  11</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#141-12">1.4.1 如何获得示例数据库 12</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#142-12">1.4.2 最低配置要求 12</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#143-13">1.4.3 如何建立和断开与服务器的连接 13</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#144-sql-15">1.4.4 执行SQL 语句 15</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#145-17">1.4.5 创建数据库 17</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#146-18">1.4.6 创建数据表 18</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#147-33">1.4.7 如何添加新的数据行 33</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#148-sampdb-36">1.4.8 将sampdb 数据库重设为原来的状态 36</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#149-37">1.4.9 检索信息 37</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1410-64">1.4.10 如何删除或更新现有的数据行 64</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#15-mysql-66">1.5 与客户程序mysql 交互的技巧 66</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#151-67">1.5.1 简化连接过程 67</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#152-69">1.5.2 减少输入查询命令时的打字动作 69</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#16-72">1.6 后面各章的学习计划 72</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#2-sql-73">第2 章 使用SQL 管理数据 73</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#21-mysql-sql-73">2.1 MySQL 服务器的SQL 模式 73</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#22-mysql-74">2.2 MySQL 标识符语法和命名规则 74</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#23-sql-77">2.3 SQL 语句中的字母大小写问题 77</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#24-78">2.4 字符集支持 78</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#241-79">2.4.1 字符集的设定 79</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#242-80">2.4.2 确定可供选用的字符集和当前设置 80</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#243-unicode-81">2.4.3 Unicode 支持 81</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#25-82">2.5 数据库的选定、创建、删除和变更 82</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#251-82">2.5.1 数据库的选定 82</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#252-82">2.5.2 数据库的创建 82</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#253-83">2.5.3 数据库的删除 83</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#254-83">2.5.4 数据库的变更 83</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#26-84">2.6 数据表的创建、删除、索引和变更 84</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#261-84">2.6.1 存储引擎的特征 84</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#262-90">2.6.2 创建数据表 90</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#263-101">2.6.3 删除数据表 101</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#264-101">2.6.4 为数据表编制索引 101</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#265-106">2.6.5 改变数据表的结构 106</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#27-108">2.7 获取数据库的元数据 108</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#271-show-109">2.7.1 用SHOW 语句获取元数据 109</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#272-information_schema-110">2.7.2 从INFORMATION_SCHEMA数据库获取元数据 110</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#273-112">2.7.3 从命令行获取元数据 112</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#28-113">2.8 利用联结操作对多个数据表进行检索 113</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#281-114">2.8.1 内联结 114</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#282-116">2.8.2 避免歧义：如何在联结操作中给出数据列的名字 116</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#283-116">2.8.3 左联结和右联结（外联结）  116</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#29-120">2.9 用子查询进行多数据表检索 120</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#291-121">2.9.1 子查询与关系比较操作符 121</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#292-in-not-in-122">2.9.2 IN 和NOT IN 子查询 122</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#293-allany-some-123">2.9.3 ALL、ANY 和SOME 子查询 123</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#294-exists-not-exists-124">2.9.4 EXISTS 和NOT EXISTS子查询 124</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#295-124">2.9.5 与主查询相关的子查询 124</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#296-from-124">2.9.6 FROM 子句中的子查询 124</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#297-125">2.9.7 把子查询改写为联结查询 125</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#210-union-126">2.10 用UNION 语句进行多数据表检索 126</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#211-129">2.11 使用视图 129</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#212-133">2.12 涉及多个数据表的删除和更新操作 133</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#213-134">2.13 事务处理 134</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2131-135">2.13.1 利用事务来保证语句的安全执行 135</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2132-139">2.13.2 使用事务保存点 139</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2133-139">2.13.3 事务的隔离性 139</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2134-140">2.13.4 事务问题的非事务解决方案 140</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#214-143">2.14 外键和引用完整性 143</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2141-144">2.14.1 外键的创建和使用 144</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2142-149">2.14.2 如果不能使用外键该怎么办 149</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#215-fulltext-150">2.15 使用FULLTEXT 索引 150</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2151-151">2.15.1 全文搜索：自然语言模式 151</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2152-153">2.15.2 全文搜索：布尔模式 153</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2153-154">2.15.3 全文搜索：查询扩展模式 154</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#2154-155">2.15.4 配置全文搜索引擎 155</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#3-156">第3 章 数据类型 156</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#31-157">3.1 数据值的类别 157</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#311-157">3.1.1 数值 157</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#312-158">3.1.2 字符串值 158</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#313-166">3.1.3 日期/时间值 166</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#314-166">3.1.4 坐标值 166</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#315-166">3.1.5 布尔值 166</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#316-null-166">3.1.6 空值NULL 166</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#32-mysql-166">3.2 MySQL 的数据类型 166</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#321-167">3.2.1 数据类型概述 167</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#322-168">3.2.2 数据表中的特殊列类型 168</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#323-169">3.2.3 指定列默认值 169</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#324-170">3.2.4 数值数据类型 170</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#325-176">3.2.5 字符串数据类型 176</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#326-189">3.2.6 日期/时间数据类型 189</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#327-196">3.2.7 空间数据类型 196</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#33-mysql-197">3.3 MySQL 如何处理非法数据值 197</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#34-199">3.4 序列 199</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#341-auto_increment-199">3.4.1 通用AUTO_INCREMENT 属性 199</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#342-auto_increment-201">3.4.2 与特定存储引擎有关的AUTO_INCREMENT 属性 201</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#343-auto_increment-203">3.4.3 使用AUTO_INCREMENT 数据列时的要点 203</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#344-auto_increment-204">3.4.4 使用AUTO_INCREMENT 机制时的注意事项 204</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#345-auto_increment-205">3.4.5 如何在不使用AUTO_INCREMENT的情况下生成序列编号 205</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#35-207">3.5 表达式求值和类型转换 207</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#351-207">3.5.1 表达式的编写 207</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#352-213">3.5.2 类型转换 213</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#36-220">3.6 数据类型的选用 220</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#361-222">3.6.1 数据列将容纳什么样的数据 222</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#362-224">3.6.2 数据是否都在某个特定的区间内 224</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#363-225">3.6.3 与挑选数据类型有关的问题是相互影响的 225</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#4-227">第4 章 存储程序 227</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#41-228">4.1 复合语句和语句分隔符 228</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#42-229">4.2 存储函数和存储过程 229</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#421-231">4.2.1 存储函数和存储过程的权限 231</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#422-232">4.2.2 存储过程的参数类型 232</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#43-233">4.3 触发器 233</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#44-234">4.4 事件 234</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#45-236">4.5 存储程序和视图的安全性 236</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#5-237">第5 章 查询优化 237</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#51-237">5.1 使用索引 237</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#511-238">5.1.1 索引的优点 238</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#512-240">5.1.2 索引的缺点 240</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#513-241">5.1.3 挑选索引 241</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#52-mysql-243">5.2 MySQL 的查询优化程序 243</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#521-244">5.2.1 查询优化器的工作原理 244</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#522-explain-247">5.2.2 用EXPLAIN 语句检查优化器操作 247</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#53-252">5.3 为提高查询效率而挑选数据类型 252</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#54-255">5.4 有效加载数据 255</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#55-258">5.5 调度和锁定问题 258</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#551-259">5.5.1 改变语句的执行优先级 259</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#552-259">5.5.2 使用延迟插入 259</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#553-260">5.5.3 使用并发插入 260</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#554-260">5.5.4 锁定级别与并发性 260</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#56-261">5.6 系统管理员所完成的优化 261</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#561-myisam-263">5.6.1 使用MyISAM键缓存 263</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#562-264">5.6.2 使用查询缓存 264</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#563-265">5.6.3 硬件优化 265</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql-6-mysql-268">第二部 分 MySQL 的编程接口第6 章 MySQL 程序设计 268</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#61-mysql-268">6.1 为什么要自己编写MySQL 程序 268</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#62-mysql-api-271">6.2 MySQL 应用程序可用的API 271</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#621-c-api-272">6.2.1 C API 272</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#622-perl-dbi-api-272">6.2.2 Perl DBI API  272</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#623-php-api-274">6.2.3 PHP API  274</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#63-api-275">6.3 如何挑选API  275</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#631-275">6.3.1 执行环境 275</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#632-276">6.3.2 性能 276</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#633-278">6.3.3 开发时间 278</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#634-280">6.3.4 可移植性 280</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#7-c-mysql-281">第7 章 用C 语言编写MySQL 程序 281</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#71-282">7.1 编译和链接客户程序 282</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#72-284">7.2 连接到服务器 284</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#73-287">7.3 出错消息和命令行选项的处理 287</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#731-287">7.3.1 出错检查 287</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#732-290">7.3.2 实时获取连接参数 290</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#733-mysql-301">7.3.3 给MySQL 客户程序增加选项处理功能 301</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#74-sql-305">7.4 处理SQL 语句 305</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#741-306">7.4.1 处理修改数据行的语句 306</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#742-307">7.4.2 处理有结果集的语句 307</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#743-310">7.4.3 一个通用的语句处理程序 310</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#744-311">7.4.4 另一种语句处理方案 311</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#745-mysqlstoreresultmysqluseresult-312">7.4.5 mysql<em>store</em>result()与mysql<em>use</em>result()函数的对比 312</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#746-314">7.4.6 使用结果集元数据 314</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#747-319">7.4.7 对特殊字符和二进制数据进行编码 319</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#75-322">7.5 交互式语句执行程序 322</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#76-ssl-323">7.6 怎样编写具备SSL 支持的客户程序 323</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#77-327">7.7 嵌入式服务器库的使用 327</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#771-328">7.7.1 编写内建了服务器的应用程序 328</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#772-330">7.7.2 生成应用程序可执行二进制文件 330</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#78-331">7.8 一次执行多条语句 331</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#79-333">7.9 使用服务器端预处理语句 333</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#8-perl-dbi-mysql-343">第8 章 使用Perl DBI 编写MySQL 程序 343</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#81-perl-343">8.1 Perl 脚本的特点 343</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#82-perl-dbi-344">8.2 Perl DBI 概述 344</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#821-dbi-344">8.2.1 DBI 数据类型 344</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#822-dbi-345">8.2.2 一个简单的DBI 脚本 345</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#823-349">8.2.3 出错处理 349</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#824-352">8.2.4 处理修改数据行的语句 352</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#825-353">8.2.5 处理返回结果集的语句 353</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#826-361">8.2.6 在语句字符串引用特殊字符 361</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#827-363">8.2.7 占位符与预处理语句 363</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#828-365">8.2.8 把查询结果绑定到脚本变量 365</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#829-366">8.2.9 设定连接参数 366</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#8210-369">8.2.10 调试 369</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#8211-372">8.2.11 使用结果集的元数据 372</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#8212-376">8.2.12 实现事务处理 376</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#83-dbi-377">8.3 DBI 脚本实战 377</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#831-377">8.3.1 生成美国历史研究会会员名录 377</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#832-382">8.3.2 发出会费催交通知 382</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#833-387">8.3.3 会员记录项的编辑修改 387</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#834-392">8.3.4 寻找志趣相同的会员 392</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#835-393">8.3.5 把会员名录放到网上 393</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#84-dbi-web-396">8.4 用DBI 开发Web 应用 396</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#841-apache-cgi-397">8.4.1 配置Apache 服务器使用CGI脚本 397</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav5" onclick="animateByNav()" href="#842-cgipm-398">8.4.2 CGI.pm 模块简介 398</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#843-webmysql-404">8.4.3 从Web脚本连接MySQL服务器 404</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#844-web-406">8.4.4 一个基于Web 的数据库浏览器 406</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#845-410">8.4.5 考试记分项目：考试分数浏览器 410</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#846-413">8.4.6 美国历史研究会：寻找志趣相同的会员 413</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#9-php-mysql-418">第9 章 用PHP 编写MySQL 程序 418</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#91-php-419">9.1 PHP 概述 419</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#911-php-421">9.1.1 一个简单的PHP 脚本 421</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#912-php-424">9.1.2 利用PHP 库文件实现代码封装 424</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#913-428">9.1.3 简单的数据检索页面 428</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#914-431">9.1.4 处理语句结果 431</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#915-null-434">9.1.5 测试查询结果里的NULL 值 434</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#916-434">9.1.6 使用预处理语句 434</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#917-435">9.1.7 利用占位符来处理带引号的数据值 435</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#918-437">9.1.8 出错处理 437</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#92-php-438">9.2 PHP 脚本实战 438</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#921-438">9.2.1 考试分数的在线录入 438</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#922-449">9.2.2 创建一个交互式在线测验 449</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#923-454">9.2.3 美国历史研究会：会员个人资料的在线修改 454</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#10-mysql-462">第10 章 MySQL 系统管理简介 462</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#101-mysql-462">10.1 MySQL 组件 462</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#102-463">10.2 常规管理 463</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#103-464">10.3 访问控制与安全性 464</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#104-464">10.4 数据库的维护、备份和复制 464</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#11-mysql-466">第11 章 MySQL 的数据目录 466</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#111-466">11.1 数据目录的位置 466</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#112-468">11.2 数据目录的层次结构 468</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1121-mysql-468">11.2.1 MySQL 服务器如何提供对数据的访问 468</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1122-mysql-469">11.2.2 MySQL 数据库在文件系统里是如何表示的 469</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1123-470">11.2.3 数据表在文件系统里的表示方式 470</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1124-471">11.2.4 视图和触发器在文件系统里的表示方式 471</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1125-sql-472">11.2.5 SQL 语句与数据表文件操作的对应关系 472</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1126-472">11.2.6 操作系统对数据库对象的命名规则有何影响 472</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1127-474">11.2.7 影响数据表最大长度的因素 474</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1128-475">11.2.8 数据目录的结构对系统性能的影响 475</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1129-mysql-477">11.2.9 MySQL 状态文件和日志文件 477</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#113-479">11.3 重新安置数据目录的内容 479</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1131-479">11.3.1 重新安置工作的具体方法 479</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1132-480">11.3.2 重新安置注意事项 480</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1133-480">11.3.3 评估重新安置的效果 480</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1134-481">11.3.4 重新安置整个数据目录 481</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1135-481">11.3.5 重新安置各个数据库 481</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1136-482">11.3.6 重新安置各个数据表 482</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1137-innodb-482">11.3.7 重新安置InnoDB 共享表空间 482</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1138-482">11.3.8 重新安置状态文件和日志文件 482</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#12-mysql-484">第12 章 MySQL 数据库系统的日常管理 484</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#121-mysql-484">12.1 安装MySQL 软件后的初始安防设置 484</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1211-mysql-485">12.1.1 为初始MySQL账户设置口令 485</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1212-489">12.1.2 为第二个服务器设置口令 489</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#122-mysql-489">12.2 安排MySQL 服务器的启动和关停 489</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1221-unix-mysql-489">12.2.1 在Unix 上运行MySQL服务器 489</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1222-windows-mysql-493">12.2.2 在Windows 上运行MySQL服务器 493</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1223-495">12.2.3 指定服务器启动选项 495</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1224-497">12.2.4 关闭服务器 497</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1225-497">12.2.5 当你未能连接至服务器时重新获得服务器的控制 497</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#123-mysql-499">12.3 对MySQL 服务器的连接监听情况进行控制 499</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#124-mysql-500">12.4 管理MySQL 用户账户 500</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1241-mysql-501">12.4.1 高级MySQL 账户管理操作 501</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1242-503">12.4.2 对账户授权 503</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1243-510">12.4.3 查看账户的权限 510</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1244-510">12.4.4 撤销权限和删除用户 510</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1245-511">12.4.5 改变口令或重新设置丢失的口令 511</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#125-512">12.5 维护日志文件 512</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1251-514">12.5.1 出错日志 514</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1252-515">12.5.2 常规查询日志 515</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1253-515">12.5.3 慢查询日志 515</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1254-516">12.5.4 二进制日志和二进制日志索引文件 516</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1255-517">12.5.5 中继日志和中继日志索引文件 517</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1256-518">12.5.6 日志数据表的使用 518</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1257-519">12.5.7 日志管理 519</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#126-mysql-524">12.6 调整MySQL 服务器 524</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1261-525">12.6.1 查看和设置系统变量的值 525</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1262-528">12.6.2 通用型系统变量 528</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1263-530">12.6.3 查看状态变量的值 530</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#127-531">12.7 存储引擎的配置 531</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1271-mysql-531">12.7.1 为MySQL 服务器挑选存储引擎 531</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1272-myisam-533">12.7.2 配置MyISAM 存储引擎 533</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1273-innodb-536">12.7.3 配置InnoDB 存储引擎 536</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1274-falcon-541">12.7.4 配置Falcon 存储引擎 541</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#128-load-data-local-541">12.8 启用或者禁用LOAD DATA 语句的LOCAL 能力 541</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#129-542">12.9 国际化和本地化问题 542</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1291-mysql-542">12.9.1 设置MySQL 服务器的地理时区 542</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1292-544">12.9.2 选择用来显示出错信息的语言 544</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1293-mysql-544">12.9.3 配置MySQL 服务器的字符集支持 544</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#1210-545">12.10 运行多个服务器 545</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#12101-545">12.10.1 运行多个服务器的问题 545</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#12102-547">12.10.2 配置和编译不同的服务器 547</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#12103-548">12.10.3 指定启动选项的决策 548</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#12104-mysqld_multi-549">12.10.4 用于服务器管理的mysqld_multi 549</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#12105-windows-mysql-550">12.10.5 在Windows 系统上运行多个MySQL 服务器 550</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#1211-mysql-553">12.11 升 级MySQL 553</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#13-555">第13 章 访问控件和安全 555</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#131-555">13.1 内部安全性：防止未经授权的文件系统访问 555</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1311-556">13.1.1 如何偷取数据 556</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1312-mysql-557">13.1.2 保护你的MySQL 安装 557</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#132-562">13.2 外部安全性：防止未经授权的网络访问 562</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1321-mysql-562">13.2.1 MySQL 权限表的结构和内容 562</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1322-568">13.2.2 服务器如何控制客户访问 568</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1323-572">13.2.3 一个关于权限的难题 572</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1324-575">13.2.4 应该回避的权限数据表风险 575</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#133-577">13.3 加密连接的建立 577</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#14-mysql-582">第14 章 MySQL 数据库的维护、备份和复制 582</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#141-582">14.1 数据库预防性维护工作的基本原则 582</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#142-mysql-583">14.2 在MySQL 服务器运行时维护数据库 583</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1421-584">14.2.1 以只读方式或读/写方式锁定一个或多个数据表 584</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1422-586">14.2.2 以只读方式锁定所有的数据库 586</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#143-587">14.3 预防性维护 587</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1431-mysql-587">14.3.1 充分利用MySQL 服务器的自动恢复能力 587</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1432-588">14.3.2 定期进行预防性维护 588</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#144-589">14.4 制作数据库备份 589</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1441-mysqldump-590">14.4.1 用mysqldump 程序制作文本备份 590</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1442-593">14.4.2 制作二进制数据库备份 593</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1443-innodbfaclcon-595">14.4.3 备份InnoDB或Faclcon数据表 595</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#145-596">14.5 把数据库复制到另一个服务器 596</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1451-596">14.5.1 使用一个备份文件来复制数据库 596</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1452-597">14.5.2 把数据库从一个服务器复制到另一个 597</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#146-598">14.6 数据表的检查和修复 598</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1461-599">14.6.1 用服务器检查和修复数据表 599</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1462-mysqlcheck-599">14.6.2 用mysqlcheck 程序检查和修复数据表 599</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1463-myisamchk-600">14.6.3 用myisamchk 程序检查和修复数据表 600</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#147-603">14.7 使用备份进行数据恢复 603</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1471-603">14.7.1 恢复整个数据库 603</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1472-604">14.7.2 恢复数据表 604</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1473-605">14.7.3 重新执行二进制日志文件里的语句 605</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1474-innodb-606">14.7.4 InnoDB 存储引擎的自动恢复功能 606</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#148-607">14.8 设置复制服务器 607</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1481-607">14.8.1 复制机制的工作原理 607</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1482-609">14.8.2 建立主从复制关系 609</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1483-611">14.8.3 二进制日志的格式 611</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#1484-612">14.8.4 使用复制机制制作备份 612</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_1">MySQL 教程</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#rdbms">RDBMS 术语</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#mysql_2">MySQL</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_1">表格的基本内容：</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#nosql">NoSQL</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_3">登录 MySQL</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_4">MySQL 的启动和关闭</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#linux">Linux</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_2">启动服务</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_3">关闭服务</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_4">重启服务</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav1" onclick="animateByNav()" href="#service-mysql-start-binsystemctl-restart-mysqlservice">原因推测：service mysql start 是重定向到/bin/systemctl restart mysql.service.</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav1" onclick="animateByNav()" href="#mysqlmysqldmysqld">mysql与mysqld是不同的，前者交互式命令（客户端），mysqld才是后端服务进程</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav1" onclick="animateByNav()" href="#_5">使用下面命令即可：</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_5">管理 MySQL 的命令</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#show-databases"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW DATABASES;</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#use"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>USE [数据库名];</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#show-tables"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW TABLES;</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#show-columns-from"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW COLUMNS FROM [数据表];</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#show-index-from"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW INDEX FROM [数据表];</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_6">MySQL 数据库操作</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#create-database"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>CREATE DATABASE [数据库名];</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#drop-database"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>DROP DATABASE [数据库名];</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#use_1"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>USE [数据库名];</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_7">MySQL 数据表操作</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#create-table-tablename-columnname-column_type">CREATE TABLE table<em>name (column</em>name column_type);</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#drop-table-table_name">DROP TABLE table_name;</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#insert-into-table_name-values">INSERT INTO table_name (&hellip;) VALUES (&hellip;)</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#select">SELECT</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#update">UPDATE</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#delete">DELETE</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#like">LIKE</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#union">UNION</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#mysql_8">MySQL 排序</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#mysql-group-by">MySQL GROUP BY 语句</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#mysql_9">MySQL 连接的使用</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mysql_10">MySQL 数据类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_6">数值类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_7">日期和时间类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav4" onclick="animateByNav()" href="#_8">字符串(字符)类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav2" onclick="animateByNav()" href="#mvcc">MVCC</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#mvcc_1">MVCC 概述</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#mvcc_2">为什么需要MVCC</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#innodb-mvcc">InnoDB MVCC实现原理</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#_9">如何组织版本链</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link nav3" onclick="animateByNav()" href="#-readview">如何实现一致性读-ReadView</a>
</li>

  </ul>
</div>

</div>
<div id="content-articles">
  <h1 id="MySQL 数据库" class="content-subhead">MySQL 数据库</h1>
  <p>
    <span>2021-04-17</span>
    <span><span class="post-category post-category-other">数据库</span></span>
    <button id="button-markdownEditor" class="pure-button" onclick="markdownEditor()">启用编辑</button>
    <button id="button-save" class="pure-button" onclick="save()">保存</button>
  </p>
  <div id="content-articles-markdownEditor" style="display: none;">
    <h1>编辑 power by pell</h1>
    <div id="editor" class="pell"></div>
    <div style="margin-top:20px;">
        <h3>Text output:</h3>
        <div id="text-output"></div>
    </div>
    <div style="margin-top:20px;">
        <h3>HTML output:</h3>
        <pre id="html-output"></pre>
    </div>
  </div>
  <div id="content-articles-markdown">
    <blockquote class="content-quote">
<p>以下内容来自于 《MySQL 技术内幕第四版》</p>
</blockquote>
<h1 id="mysql">第一部分 MySQL 基础知识</h1>
<h2 id="1-mysql-sql-2">第1 章 MySQL 和SQL 入门 2</h2>
<h3 id="11-mysql-2">1.1 MySQL 的用途 2</h3>
<h3 id="12-4">1.2 示例数据库 4</h3>
<h4 id="121-5">1.2.1 “美国历史研究会”场景 5</h4>
<h4 id="122-7">1.2.2 考试记分项目 7</h4>
<h4 id="123-7">1.2.3 关于示例数据库的说明 7</h4>
<h3 id="13-7">1.3 数据库基本术语 7</h3>
<h4 id="131-8">1.3.1 数据库的组织结构 8</h4>
<p>MySQL 是一种关系数据库管理系统（Relation Database Management System，RDBMS）</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>MySQL</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>数据库</td>
<td>database</td>
<td>R<strong>DB</strong>MS</td>
<td>▶︎ 数据库里的数据集合都存放在数据表（table）里； <br />▶︎ 数据表由数据行（row）和数据列（column）构成； <br />▶︎ 一个数据行就是数据表里的一条记录（record）； <br />▶︎ 记录可以包含多个信息项，数据表里的每一个数据列都对应一个信息项。</td>
</tr>
<tr>
<td>管理系统</td>
<td>management system</td>
<td>RDB<strong>MS</strong></td>
<td>指的是用来对数据进行 <strong>插入、检索、修改、删除</strong> 等操作的软件。</td>
</tr>
<tr>
<td>关系</td>
<td>relational</td>
<td><strong>R</strong>DBMS</td>
<td>▶︎ 表示 RDBMS 是 DBMS 中的一种；<br />▶︎ 这种 DBMS 的专长就是把分别存放在两个数据表里的信息联系（即相互匹配）起来，这种联系是通过查找两个数据表的共同元素来实现的。<br />▶︎ RDBMS 的威力在于他能方便地抽取出数据表里的数据并把他们与其他相关的数据表信息结合起来，为那些单独利用某个数据表无法找到答案的问题提供答案。</td>
</tr>
</tbody>
</table></div>
<p><img class="pure-img" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-数据库.assets/截屏2021-04-21 21.28.03.png" alt="截屏2021-04-21 21.28.03" style="zoom:50%;" /></p>
<p><img class="pure-img" alt="image-20210422113443417" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422113443417.png" /></p>
<h4 id="132-10">1.3.2 数据库查询语言 10</h4>
<p>SQL（Structured Query Language，结构化查询语言）</p>
<p>SQL 是今天标准化数据库语言。</p>
<h4 id="133-mysql-10">1.3.3 MySQL 的体系结构 10</h4>
<p>MySQL 采用的是客户/客户服务器体系结构。</p>
<ul>
<li>
<p>MySQL 服务器程序（mysql 程序）运行在存放着你的数据库的机器上，负责在网络上监听并处理来自客户的服务请求，根据这些请求去访问数据库，再把有关信息回传给客户。</p>
</li>
<li>
<p>MySQL 客户程序，负责连接到数据库服务器，并通过向服务器发出查询命令来告知他们需要哪些信息。</p>
</li>
</ul>
<h3 id="14-mysql-11">1.4 MySQL  11</h3>
<h4 id="141-12">1.4.1 如何获得示例数据库 12</h4>
<h4 id="142-12">1.4.2 最低配置要求 12</h4>
<h4 id="143-13">1.4.3 如何建立和断开与服务器的连接 13</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">$ mysql -h host_name -u user_name -p
Enter password:

--host = host_name
--user = user_name
</code></span></code></pre>
<h4 id="144-sql-15">1.4.4 执行SQL 语句 15</h4>
<h4 id="145-17">1.4.5 创建数据库 17</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; CREATE DATABASE database_name;
mysql&gt; USE database_name;
mysql&gt; SELECT DATABASE();
</code></span></code></pre>
<p>启动 MySQL 时指定数据库</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">$ mysql database_name;
</code></span></code></pre>
<h4 id="146-18">1.4.6 创建数据表 18</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; CREATE TABLE tbl_name(column_speces);
</code></span></code></pre>
<h4 id="147-33">1.4.7 如何添加新的数据行 33</h4>
<h4 id="148-sampdb-36">1.4.8 将sampdb 数据库重设为原来的状态 36</h4>
<h4 id="149-37">1.4.9 检索信息 37</h4>
<h4 id="1410-64">1.4.10 如何删除或更新现有的数据行 64</h4>
<h3 id="15-mysql-66">1.5 与客户程序mysql 交互的技巧 66</h3>
<h4 id="151-67">1.5.1 简化连接过程 67</h4>
<h4 id="152-69">1.5.2 减少输入查询命令时的打字动作 69</h4>
<h3 id="16-72">1.6 后面各章的学习计划 72</h3>
<h2 id="2-sql-73">第2 章 使用SQL 管理数据 73</h2>
<h3 id="21-mysql-sql-73">2.1 MySQL 服务器的SQL 模式 73</h3>
<h3 id="22-mysql-74">2.2 MySQL 标识符语法和命名规则 74</h3>
<h3 id="23-sql-77">2.3 SQL 语句中的字母大小写问题 77</h3>
<h3 id="24-78">2.4 字符集支持 78</h3>
<h4 id="241-79">2.4.1 字符集的设定 79</h4>
<h4 id="242-80">2.4.2 确定可供选用的字符集和当前设置 80</h4>
<h4 id="243-unicode-81">2.4.3 Unicode 支持 81</h4>
<h3 id="25-82">2.5 数据库的选定、创建、删除和变更 82</h3>
<h4 id="251-82">2.5.1 数据库的选定 82</h4>
<h4 id="252-82">2.5.2 数据库的创建 82</h4>
<h4 id="253-83">2.5.3 数据库的删除 83</h4>
<h4 id="254-83">2.5.4 数据库的变更 83</h4>
<h3 id="26-84">2.6 数据表的创建、删除、索引和变更 84</h3>
<h4 id="261-84">2.6.1 存储引擎的特征 84</h4>
<h4 id="262-90">2.6.2 创建数据表 90</h4>
<h4 id="263-101">2.6.3 删除数据表 101</h4>
<h4 id="264-101">2.6.4 为数据表编制索引 101</h4>
<h4 id="265-106">2.6.5 改变数据表的结构 106</h4>
<h3 id="27-108">2.7 获取数据库的元数据 108</h3>
<h4 id="271-show-109">2.7.1 用SHOW 语句获取元数据 109</h4>
<h4 id="272-information_schema-110">2.7.2 从INFORMATION_SCHEMA数据库获取元数据 110</h4>
<h4 id="273-112">2.7.3 从命令行获取元数据 112</h4>
<h3 id="28-113">2.8 利用联结操作对多个数据表进行检索 113</h3>
<h4 id="281-114">2.8.1 内联结 114</h4>
<h4 id="282-116">2.8.2 避免歧义：如何在联结操作中给出数据列的名字 116</h4>
<h4 id="283-116">2.8.3 左联结和右联结（外联结）  116</h4>
<h3 id="29-120">2.9 用子查询进行多数据表检索 120</h3>
<h4 id="291-121">2.9.1 子查询与关系比较操作符 121</h4>
<h4 id="292-in-not-in-122">2.9.2 IN 和NOT IN 子查询 122</h4>
<h4 id="293-allany-some-123">2.9.3 ALL、ANY 和SOME 子查询 123</h4>
<h4 id="294-exists-not-exists-124">2.9.4 EXISTS 和NOT EXISTS子查询 124</h4>
<h4 id="295-124">2.9.5 与主查询相关的子查询 124</h4>
<h4 id="296-from-124">2.9.6 FROM 子句中的子查询 124</h4>
<h4 id="297-125">2.9.7 把子查询改写为联结查询 125</h4>
<h3 id="210-union-126">2.10 用UNION 语句进行多数据表检索 126</h3>
<h3 id="211-129">2.11 使用视图 129</h3>
<h3 id="212-133">2.12 涉及多个数据表的删除和更新操作 133</h3>
<h3 id="213-134">2.13 事务处理 134</h3>
<p>事务是作为一个不可分割的逻辑单元而被执行的一组 SQL 语句。</p>
<p>事务处理是通过提交（submit）和回滚（rollback）功能实现的。</p>
<ul>
<li>某个事务里的所有语句都执行成功，提交该事务将把那些语句的执行效果永久性地记录到数据库。</li>
<li>如果在事务的执行过程中发生错误，回滚该事务把发生错误之前已经执行的语句全部取消。</li>
</ul>
<p>MySQL 在执行每一条 SQL 语句时都会自动地对该语句所涉及的资源进行锁定以避免个语句之间相互干扰。</p>
<p>事务机制的特性：</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>ACID 原则</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Atomic</td>
<td>原子性</td>
<td>构成一个事务的所有语句应该是一个独立的逻辑单元，要么全部执行成功，要么一个都不成功。你不能只执行他们当中的一部分。</td>
</tr>
<tr>
<td>Consistent</td>
<td>稳定性</td>
<td>数据库在事务开始执行之前和事务执行完毕之后都必须是稳定的。</td>
</tr>
<tr>
<td>Isolated</td>
<td>孤立性</td>
<td>事务不应该相互影响。</td>
</tr>
<tr>
<td>Durable</td>
<td>可靠性</td>
<td>如果事务执行成功，它的影响将被永久性地记录到数据库里。</td>
</tr>
</tbody>
</table></div>
<h4 id="2131-135">2.13.1 利用事务来保证语句的安全执行 135</h4>
<p>使用事务，必须使用一种 <strong>支持事务处理的存储引擎：InnoDB 或 Falcon</strong>。</p>
<p>MyISAM 和 MEMORY 等其他存储引擎都不行。</p>
<p>执行事务的常用办法是发出一条 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>START TRANSACTION</code></span> 或 （<span style="overflow-x: auto; max-width:100%; display:inline;"><code>BEGIN</code></span>）语句挂起自动提交模式，然后执行构成本次事务的各条语句，最后用一条 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>COMMIT</code></span> 语句结束事务，并把他们作出的修改永久性地记入数据库。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; START TRANSACTION; (或者 BEGIN)
mysql&gt; ... 事务
mysql&gt; COMMIT; 
-- 在 COMMIT; 执行之前，事务进行的操作对第二个 mysql 进程不可见。
</code></span></code></pre>
<p>在事务过程中发生错误，可以用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ROLLBACK</code></span> 撤销事务，并把数据库恢复到事务开始之前的状态。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; ROLLBACK;
-- 接下来会将数据库回到 START TRANSACTION; 执行之前的状态。
</code></span></code></pre>
<h4 id="2132-139">2.13.2 使用事务保存点 139</h4>
<h4 id="2133-139">2.13.3 事务的隔离性 139</h4>
<p>因为 MySQL 是一个多用户数据库系统，所以不同的客户可能会在同一时间试图访问同一个数据表。</p>
<blockquote class="content-quote">
<p>待补充&hellip;</p>
</blockquote>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>引擎</th>
<th>锁</th>
<th>效果</th>
</tr>
</thead>
<tbody>
<tr>
<td>MyISAM</td>
<td>数据表级锁</td>
<td>导致并发性能下降</td>
</tr>
<tr>
<td>InnoDB</td>
<td>数据行级锁</td>
<td></td>
</tr>
</tbody>
</table></div>
<p>未使用隔离级别可能产生的问题：</p>
<ul>
<li>脏读：指某个事务所作出的修改在它尚未被提交时就可以被其他事务看到。</li>
<li>不可重复读取：指同一个事务使用同一条 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 语句每次读取到的结果不一样。</li>
<li>事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> </li>
<li>事务二对数据进行了修改</li>
<li>事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span></li>
<li>幻影数据行</li>
<li>事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> </li>
<li>事务二添加了某些数据</li>
<li>事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span></li>
</ul>
<p>InnoDB 存储引擎的 4 种事务隔离级别机制</p>
<p><img class="pure-img" alt="image-20210422142537592" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422142537592.png" /></p>
<p>InnoDB 存储引擎的默认隔离级别是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>REPEATABLE READ</code></span></p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>隔离级别</th>
<th>含义</th>
<th>脏读</th>
<th>不可重复读</th>
<th>幻影数据行</th>
</tr>
</thead>
<tbody>
<tr>
<td>Read uncommitted</td>
<td>读未提交</td>
<td>是</td>
<td>是</td>
<td>是</td>
</tr>
<tr>
<td>Read committed</td>
<td>读已提交</td>
<td></td>
<td>是</td>
<td>是</td>
</tr>
<tr>
<td>Repeatable read</td>
<td>可重复读</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Serializable</td>
<td>串行化</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table></div>
<h4 id="2134-140">2.13.4 事务问题的非事务解决方案 140</h4>
<p>明确地锁定数据表。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; LOCK TABLES tbl_name WRITE;
mysql&gt; ...
mysql&gt; UNLOCK TABLES;
</code></span></code></pre>
<p>使用相对更新操作，不使用就对更新操作。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">-- 绝对更新操作：
mysql&gt; 找出值
mysql&gt; 提交修改后的值
-- 相对更新操作：
mysql&gt; 提交（值 + 运算）
mysql&gt; UPDATE tbl_name SET val = val + num WHERE item = 'str'
</code></span></code></pre>
<h3 id="214-143">2.14 外键和引用完整性 143</h3>
<p><strong>外键</strong> 关系可以在某个数据表里声明与另一个数据表里的某个索引相关联的索引。</p>
<p><strong>级联删除</strong> 根据外键删除同时另一个表里的数据。</p>
<p>术语：</p>
<ul>
<li>父表，包含原始键值的数据表；</li>
<li>父表中的键值用来关联两个数据表。</li>
<li>子表，引用父表中的键值的相关数据表。</li>
<li>子表中的某个索引引用父表中的某个索引。</li>
<li>子表的索引值必须匹配父表中的索引值或是被设置为 NULL 以表明在父表里不存爱与之对应的数据行。</li>
<li>子表里的索引就是所谓的“外键”，外键可以被设置成不允许 NULL 值。</li>
</ul>
<h4 id="2141-144">2.14.1 外键的创建和使用 144</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">[CONSTRAINT constraint_name]            
-- 用来给外键约束取名字。
FOREIGN KEY [fk_name] (index_columns)   
-- 列出子表里的被索引数据列，他们必须匹配父表的索引值。
REFERENCES tbl_name (index_columns) 
-- 列出父表和子表中的索引数据列的名字，
-- 子表里的外键将引用这个子句所列出的父表数据列。
[ON DELETE action]
-- 用来设定在父表里的数据行被删除时子表应该发生什么事，
-- 如果没有 ON DELETE，其默认行为是拒绝从父表里删除仍有子表数据行在引用他们的数据行。
-- [ON DELETE NO ACTION] 和 [ON DELETE RESTRICT]: 其含义与省略 ON DELETE 子句一样。
-- [ON DELETE CASCADE]: 在删除父表数据行时，子表里与之相关联的数据行也将被删除。
-- [ON DELETE SET NULL]: 在刪除父表数据行时，子表里与之相关联的索引列将被设置为 NULL
[ON UPDATE action]
-- 用来设定当父表里的数据行更新时子表应该发生什么事，
-- 如果没有 ON UPDATE，其默认行为是拒绝插入或更新其外键值在父表索引里没有任何匹配的子表数据行，并组织任有子表数据行在引用他们的父表索引值被更新。
[MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
</code></span></code></pre>
<h4 id="2142-149">2.14.2 如果不能使用外键该怎么办 149</h4>
<h3 id="215-fulltext-150">2.15 使用FULLTEXT 索引 150</h3>
<p>全文索引的基础是 FULLTEXT 索引，这种索引只能在 MyISAN 数据表里创建。</p>
<p>FULLTEXT 索引只能由 CHAR、VARCHAR 和 TEXT 这几种类型数据列构成。</p>
<h4 id="2151-151">2.15.1 全文搜索：自然语言模式 151</h4>
<h4 id="2152-153">2.15.2 全文搜索：布尔模式 153</h4>
<h4 id="2153-154">2.15.3 全文搜索：查询扩展模式 154</h4>
<h4 id="2154-155">2.15.4 配置全文搜索引擎 155</h4>
<h2 id="3-156">第3 章 数据类型 156</h2>
<h3 id="31-157">3.1 数据值的类别 157</h3>
<h4 id="311-157">3.1.1 数值 157</h4>
<h4 id="312-158">3.1.2 字符串值 158</h4>
<h4 id="313-166">3.1.3 日期/时间值 166</h4>
<h4 id="314-166">3.1.4 坐标值 166</h4>
<h4 id="315-166">3.1.5 布尔值 166</h4>
<h4 id="316-null-166">3.1.6 空值NULL 166</h4>
<h3 id="32-mysql-166">3.2 MySQL 的数据类型 166</h3>
<h4 id="321-167">3.2.1 数据类型概述 167</h4>
<h4 id="322-168">3.2.2 数据表中的特殊列类型 168</h4>
<h4 id="323-169">3.2.3 指定列默认值 169</h4>
<h4 id="324-170">3.2.4 数值数据类型 170</h4>
<p><img class="pure-img" alt="image-20210422165256096" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165256096.png" /></p>
<p><img class="pure-img" alt="image-20210422165508551" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165508551.png" /></p>
<p><img class="pure-img" alt="image-20210422165531028" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165531028.png" /></p>
<p><img class="pure-img" alt="image-20210422165635309" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165635309.png" /></p>
<h4 id="325-176">3.2.5 字符串数据类型 176</h4>
<p><img class="pure-img" alt="image-20210422165314904" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165314904.png" /></p>
<p><img class="pure-img" alt="image-20210422165713216" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165713216.png" /></p>
<p><img class="pure-img" alt="image-20210422165735407" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165735407.png" /></p>
<p><img class="pure-img" alt="image-20210422165806500" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165806500.png" /></p>
<h4 id="326-189">3.2.6 日期/时间数据类型 189</h4>
<p><img class="pure-img" alt="image-20210422165335036" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165335036.png" /></p>
<p><img class="pure-img" alt="image-20210422165822972" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165822972.png" /></p>
<p><img class="pure-img" alt="image-20210422165838772" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165838772.png" /></p>
<p><img class="pure-img" alt="image-20210422165859148" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165859148.png" /></p>
<p><img class="pure-img" alt="image-20210422165924166" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165924166.png" /></p>
<h4 id="327-196">3.2.7 空间数据类型 196</h4>
<p><img class="pure-img" alt="image-20210422165349205" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165349205.png" /></p>
<p><img class="pure-img" alt="image-20210422165939128" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422165939128.png" /></p>
<h3 id="33-mysql-197">3.3 MySQL 如何处理非法数据值 197</h3>
<h3 id="34-199">3.4 序列 199</h3>
<h4 id="341-auto_increment-199">3.4.1 通用AUTO_INCREMENT 属性 199</h4>
<ul>
<li><strong>每个数据表只能有一个数据列具备 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span>属性，而且它应该有一种数据类型。</strong></li>
<li>必须给该数据列添加索引。使用一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>PRIMARY KEY</code></span> 或 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>YNIQUE</code></span>索引的情况最常见。</li>
<li><strong>必须给该数据列添加一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>NOT NULL</code></span> 约束条件。</strong></li>
<li>把 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>NULL</code></span>值插入 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 数据列将使 MySQL 自动生成下一个序列编号并把该值插入该数据列。</li>
<li>默认情况下，把 0 插入一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 数据列与插入 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>NULL</code></span> 相同。</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span>序列通常从 1 开始一次单步递增。</li>
<li>最近生成的序列号值可以通过调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>LAST_INSERT_ID()</code></span> 函数获得。</li>
<li>插入一个非 0 值或非 NULL 值</li>
<li>该值在已经存在，发生键重复错误。</li>
<li>该值不存在，则插入（插入数大于最大 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 将使计数值从该插入值之后开始计数）</li>
</ul>
<h4 id="342-auto_increment-201">3.4.2 与特定存储引擎有关的AUTO_INCREMENT 属性 201</h4>
<h4 id="343-auto_increment-203">3.4.3 使用AUTO_INCREMENT 数据列时的要点 203</h4>
<ul>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 不是一种数据列类型，只是数据列类型的一个属性。</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 机制的正确用途是生成一个正整数序列。</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 的最大值由数据列类型决定。</li>
<li>使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>TRUNCTAE TABEL</code></span> 语句清除某个数据表的内容，将导致该数据表中的计数序列被重置为从 1 开始计数。</li>
</ul>
<h4 id="344-auto_increment-204">3.4.4 使用AUTO_INCREMENT 机制时的注意事项 204</h4>
<h4 id="345-auto_increment-205">3.4.5 如何在不使用AUTO_INCREMENT的情况下生成序列编号 205</h4>
<p>使用带参数的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>LAST_INSERT_ID()</code></span> 函数。</p>
<ol>
<li>用函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>LAST_INSERT_ID(expr)</code></span> 插入或修改了一个数据列</li>
<li>用不带参数的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>LAST_INSERT_ID()</code></span> 函数，得到的结果将是 expr 的值。</li>
</ol>
<p><strong>需要一个自增序列：</strong></p>
<p>创建只有一个数据行的数据表</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; CREATE TABLE seq_table (seq INT UNSIGNED NOT NULL);
mysql&gt; INTO seq_table VABLE(0);
mysql&gt; UPDATE seq_table SET seq = LAST_INSERT_ID(seq+1);
mysql&gt; SELECT LAST_INSERT_ID();

-- 可以利用该方法产生步进为 2 的序列
mysql&gt; UPDATE seq_table SET seq = LAST_INSERT_ID(seq+2);
</code></span></code></pre>
<p><strong>需要多个自增序列：</strong></p>
<p>创建只有 2 个数据列的数据表：第 1 列表示计数器的编号，第 2 列表示计数器的值。</p>
<h3 id="35-207">3.5 表达式求值和类型转换 207</h3>
<h4 id="351-207">3.5.1 表达式的编写 207</h4>
<p><img class="pure-img" alt="image-20210422172610441" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422172610441.png" /></p>
<p><img class="pure-img" alt="image-20210422172635064" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422172635064.png" /></p>
<p><img class="pure-img" alt="image-20210422172649693" src="https://zromyk.gitee.io/myblog-figurebed/post/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/image-20210422172649693.png" /></p>
<h4 id="352-213">3.5.2 类型转换 213</h4>
<h3 id="36-220">3.6 数据类型的选用 220</h3>
<h4 id="361-222">3.6.1 数据列将容纳什么样的数据 222</h4>
<h4 id="362-224">3.6.2 数据是否都在某个特定的区间内 224</h4>
<h4 id="363-225">3.6.3 与挑选数据类型有关的问题是相互影响的 225</h4>
<h2 id="4-227">第4 章 存储程序 227</h2>
<ul>
<li>存储函数：返回一个计算结果。</li>
<li>存储过程：不直接返回一个结果，但可以用来完成一般的运算或是生成一个结果集并传递回客户。</li>
<li>触发器：与数据表相关联，当那个数据表被 INSERT、DELETE 或 UPDATE 语句修改时，触发器将自动执行。</li>
<li>事件：根据时间表在预定时刻自动执行。</li>
</ul>
<h3 id="41-228">4.1 复合语句和语句分隔符 228</h3>
<h3 id="42-229">4.2 存储函数和存储过程 229</h3>
<h4 id="421-231">4.2.1 存储函数和存储过程的权限 231</h4>
<h4 id="422-232">4.2.2 存储过程的参数类型 232</h4>
<h3 id="43-233">4.3 触发器 233</h3>
<h3 id="44-234">4.4 事件 234</h3>
<h3 id="45-236">4.5 存储程序和视图的安全性 236</h3>
<h2 id="5-237">第5 章 查询优化 237</h2>
<h3 id="51-237">5.1 使用索引 237</h3>
<p>用来加快查询的技术中最重要的是索引。</p>
<h4 id="511-238">5.1.1 索引的优点 238</h4>
<p>对于不同的存储引擎，索引实现的细节有所不同。</p>
<p>MyISAM ：数据表的数据行是在数据文件里，而索引值在索引文件里。</p>
<p>InnoDB ：使用表空间，在表空间里，它管理者所有 InnoDB 类型数据表的数据和索引存储。</p>
<h4 id="512-240">5.1.2 索引的缺点 240</h4>
<p>降低了在带索引的数据列里插入、删除以及修改数值的速度。</p>
<p>索引需要占据磁盘空间。</p>
<h4 id="513-241">5.1.3 挑选索引 241</h4>
<h3 id="52-mysql-243">5.2 MySQL 的查询优化程序 243</h3>
<h4 id="521-244">5.2.1 查询优化器的工作原理 244</h4>
<h4 id="522-explain-247">5.2.2 用EXPLAIN 语句检查优化器操作 247</h4>
<h3 id="53-252">5.3 为提高查询效率而挑选数据类型 252</h3>
<h3 id="54-255">5.4 有效加载数据 255</h3>
<h3 id="55-258">5.5 调度和锁定问题 258</h3>
<h4 id="551-259">5.5.1 改变语句的执行优先级 259</h4>
<h4 id="552-259">5.5.2 使用延迟插入 259</h4>
<h4 id="553-260">5.5.3 使用并发插入 260</h4>
<h4 id="554-260">5.5.4 锁定级别与并发性 260</h4>
<h3 id="56-261">5.6 系统管理员所完成的优化 261</h3>
<h4 id="561-myisam-263">5.6.1 使用MyISAM键缓存 263</h4>
<h4 id="562-264">5.6.2 使用查询缓存 264</h4>
<h4 id="563-265">5.6.3 硬件优化 265</h4>
<h2 id="mysql-6-mysql-268">第二部 分 MySQL 的编程接口第6 章 MySQL 程序设计 268</h2>
<h3 id="61-mysql-268">6.1 为什么要自己编写MySQL 程序 268</h3>
<h3 id="62-mysql-api-271">6.2 MySQL 应用程序可用的API 271</h3>
<h4 id="621-c-api-272">6.2.1 C API 272</h4>
<h4 id="622-perl-dbi-api-272">6.2.2 Perl DBI API  272</h4>
<h4 id="623-php-api-274">6.2.3 PHP API  274</h4>
<h3 id="63-api-275">6.3 如何挑选API  275</h3>
<h4 id="631-275">6.3.1 执行环境 275</h4>
<h4 id="632-276">6.3.2 性能 276</h4>
<h4 id="633-278">6.3.3 开发时间 278</h4>
<h4 id="634-280">6.3.4 可移植性 280</h4>
<h2 id="7-c-mysql-281">第7 章 用C 语言编写MySQL 程序 281</h2>
<h3 id="71-282">7.1 编译和链接客户程序 282</h3>
<h3 id="72-284">7.2 连接到服务器 284</h3>
<h3 id="73-287">7.3 出错消息和命令行选项的处理 287</h3>
<h4 id="731-287">7.3.1 出错检查 287</h4>
<h4 id="732-290">7.3.2 实时获取连接参数 290</h4>
<h4 id="733-mysql-301">7.3.3 给MySQL 客户程序增加选项处理功能 301</h4>
<h3 id="74-sql-305">7.4 处理SQL 语句 305</h3>
<h4 id="741-306">7.4.1 处理修改数据行的语句 306</h4>
<h4 id="742-307">7.4.2 处理有结果集的语句 307</h4>
<h4 id="743-310">7.4.3 一个通用的语句处理程序 310</h4>
<h4 id="744-311">7.4.4 另一种语句处理方案 311</h4>
<h4 id="745-mysqlstoreresultmysqluseresult-312">7.4.5 mysql<em>store</em>result()与mysql<em>use</em>result()函数的对比 312</h4>
<h4 id="746-314">7.4.6 使用结果集元数据 314</h4>
<h4 id="747-319">7.4.7 对特殊字符和二进制数据进行编码 319</h4>
<h3 id="75-322">7.5 交互式语句执行程序 322</h3>
<h3 id="76-ssl-323">7.6 怎样编写具备SSL 支持的客户程序 323</h3>
<h3 id="77-327">7.7 嵌入式服务器库的使用 327</h3>
<h4 id="771-328">7.7.1 编写内建了服务器的应用程序 328</h4>
<h4 id="772-330">7.7.2 生成应用程序可执行二进制文件 330</h4>
<h3 id="78-331">7.8 一次执行多条语句 331</h3>
<h3 id="79-333">7.9 使用服务器端预处理语句 333</h3>
<h2 id="8-perl-dbi-mysql-343">第8 章 使用Perl DBI 编写MySQL 程序 343</h2>
<h3 id="81-perl-343">8.1 Perl 脚本的特点 343</h3>
<h3 id="82-perl-dbi-344">8.2 Perl DBI 概述 344</h3>
<h4 id="821-dbi-344">8.2.1 DBI 数据类型 344</h4>
<h4 id="822-dbi-345">8.2.2 一个简单的DBI 脚本 345</h4>
<h4 id="823-349">8.2.3 出错处理 349</h4>
<h4 id="824-352">8.2.4 处理修改数据行的语句 352</h4>
<h4 id="825-353">8.2.5 处理返回结果集的语句 353</h4>
<h4 id="826-361">8.2.6 在语句字符串引用特殊字符 361</h4>
<h4 id="827-363">8.2.7 占位符与预处理语句 363</h4>
<h4 id="828-365">8.2.8 把查询结果绑定到脚本变量 365</h4>
<h4 id="829-366">8.2.9 设定连接参数 366</h4>
<h4 id="8210-369">8.2.10 调试 369</h4>
<h4 id="8211-372">8.2.11 使用结果集的元数据 372</h4>
<h4 id="8212-376">8.2.12 实现事务处理 376</h4>
<h3 id="83-dbi-377">8.3 DBI 脚本实战 377</h3>
<h4 id="831-377">8.3.1 生成美国历史研究会会员名录 377</h4>
<h4 id="832-382">8.3.2 发出会费催交通知 382</h4>
<h4 id="833-387">8.3.3 会员记录项的编辑修改 387</h4>
<h4 id="834-392">8.3.4 寻找志趣相同的会员 392</h4>
<h4 id="835-393">8.3.5 把会员名录放到网上 393</h4>
<h3 id="84-dbi-web-396">8.4 用DBI 开发Web 应用 396</h3>
<h4 id="841-apache-cgi-397">8.4.1 配置Apache 服务器使用CGI脚本 397</h4>
<h5 id="842-cgipm-398">8.4.2 CGI.pm 模块简介 398</h5>
<h4 id="843-webmysql-404">8.4.3 从Web脚本连接MySQL服务器 404</h4>
<h4 id="844-web-406">8.4.4 一个基于Web 的数据库浏览器 406</h4>
<h4 id="845-410">8.4.5 考试记分项目：考试分数浏览器 410</h4>
<h4 id="846-413">8.4.6 美国历史研究会：寻找志趣相同的会员 413</h4>
<h2 id="9-php-mysql-418">第9 章 用PHP 编写MySQL 程序 418</h2>
<h3 id="91-php-419">9.1 PHP 概述 419</h3>
<h4 id="911-php-421">9.1.1 一个简单的PHP 脚本 421</h4>
<h4 id="912-php-424">9.1.2 利用PHP 库文件实现代码封装 424</h4>
<h4 id="913-428">9.1.3 简单的数据检索页面 428</h4>
<h4 id="914-431">9.1.4 处理语句结果 431</h4>
<h4 id="915-null-434">9.1.5 测试查询结果里的NULL 值 434</h4>
<h4 id="916-434">9.1.6 使用预处理语句 434</h4>
<h4 id="917-435">9.1.7 利用占位符来处理带引号的数据值 435</h4>
<h4 id="918-437">9.1.8 出错处理 437</h4>
<h3 id="92-php-438">9.2 PHP 脚本实战 438</h3>
<h4 id="921-438">9.2.1 考试分数的在线录入 438</h4>
<h4 id="922-449">9.2.2 创建一个交互式在线测验 449</h4>
<h4 id="923-454">9.2.3 美国历史研究会：会员个人资料的在线修改 454</h4>
<p>第三部分 MySQL 的系统管理</p>
<h2 id="10-mysql-462">第10 章 MySQL 系统管理简介 462</h2>
<h3 id="101-mysql-462">10.1 MySQL 组件 462</h3>
<h3 id="102-463">10.2 常规管理 463</h3>
<h3 id="103-464">10.3 访问控制与安全性 464</h3>
<h3 id="104-464">10.4 数据库的维护、备份和复制 464</h3>
<h2 id="11-mysql-466">第11 章 MySQL 的数据目录 466</h2>
<h3 id="111-466">11.1 数据目录的位置 466</h3>
<h3 id="112-468">11.2 数据目录的层次结构 468</h3>
<h4 id="1121-mysql-468">11.2.1 MySQL 服务器如何提供对数据的访问 468</h4>
<h4 id="1122-mysql-469">11.2.2 MySQL 数据库在文件系统里是如何表示的 469</h4>
<h4 id="1123-470">11.2.3 数据表在文件系统里的表示方式 470</h4>
<h4 id="1124-471">11.2.4 视图和触发器在文件系统里的表示方式 471</h4>
<h4 id="1125-sql-472">11.2.5 SQL 语句与数据表文件操作的对应关系 472</h4>
<h4 id="1126-472">11.2.6 操作系统对数据库对象的命名规则有何影响 472</h4>
<h4 id="1127-474">11.2.7 影响数据表最大长度的因素 474</h4>
<h4 id="1128-475">11.2.8 数据目录的结构对系统性能的影响 475</h4>
<h4 id="1129-mysql-477">11.2.9 MySQL 状态文件和日志文件 477</h4>
<h3 id="113-479">11.3 重新安置数据目录的内容 479</h3>
<h4 id="1131-479">11.3.1 重新安置工作的具体方法 479</h4>
<h4 id="1132-480">11.3.2 重新安置注意事项 480</h4>
<h4 id="1133-480">11.3.3 评估重新安置的效果 480</h4>
<h4 id="1134-481">11.3.4 重新安置整个数据目录 481</h4>
<h4 id="1135-481">11.3.5 重新安置各个数据库 481</h4>
<h4 id="1136-482">11.3.6 重新安置各个数据表 482</h4>
<h4 id="1137-innodb-482">11.3.7 重新安置InnoDB 共享表空间 482</h4>
<h4 id="1138-482">11.3.8 重新安置状态文件和日志文件 482</h4>
<h2 id="12-mysql-484">第12 章 MySQL 数据库系统的日常管理 484</h2>
<h3 id="121-mysql-484">12.1 安装MySQL 软件后的初始安防设置 484</h3>
<h4 id="1211-mysql-485">12.1.1 为初始MySQL账户设置口令 485</h4>
<h4 id="1212-489">12.1.2 为第二个服务器设置口令 489</h4>
<h3 id="122-mysql-489">12.2 安排MySQL 服务器的启动和关停 489</h3>
<h4 id="1221-unix-mysql-489">12.2.1 在Unix 上运行MySQL服务器 489</h4>
<h4 id="1222-windows-mysql-493">12.2.2 在Windows 上运行MySQL服务器 493</h4>
<h4 id="1223-495">12.2.3 指定服务器启动选项 495</h4>
<h4 id="1224-497">12.2.4 关闭服务器 497</h4>
<h4 id="1225-497">12.2.5 当你未能连接至服务器时重新获得服务器的控制 497</h4>
<h3 id="123-mysql-499">12.3 对MySQL 服务器的连接监听情况进行控制 499</h3>
<h3 id="124-mysql-500">12.4 管理MySQL 用户账户 500</h3>
<h4 id="1241-mysql-501">12.4.1 高级MySQL 账户管理操作 501</h4>
<h4 id="1242-503">12.4.2 对账户授权 503</h4>
<h4 id="1243-510">12.4.3 查看账户的权限 510</h4>
<h4 id="1244-510">12.4.4 撤销权限和删除用户 510</h4>
<h4 id="1245-511">12.4.5 改变口令或重新设置丢失的口令 511</h4>
<h3 id="125-512">12.5 维护日志文件 512</h3>
<h4 id="1251-514">12.5.1 出错日志 514</h4>
<h4 id="1252-515">12.5.2 常规查询日志 515</h4>
<h4 id="1253-515">12.5.3 慢查询日志 515</h4>
<h4 id="1254-516">12.5.4 二进制日志和二进制日志索引文件 516</h4>
<h4 id="1255-517">12.5.5 中继日志和中继日志索引文件 517</h4>
<h4 id="1256-518">12.5.6 日志数据表的使用 518</h4>
<h4 id="1257-519">12.5.7 日志管理 519</h4>
<h3 id="126-mysql-524">12.6 调整MySQL 服务器 524</h3>
<h4 id="1261-525">12.6.1 查看和设置系统变量的值 525</h4>
<h4 id="1262-528">12.6.2 通用型系统变量 528</h4>
<h4 id="1263-530">12.6.3 查看状态变量的值 530</h4>
<h3 id="127-531">12.7 存储引擎的配置 531</h3>
<h4 id="1271-mysql-531">12.7.1 为MySQL 服务器挑选存储引擎 531</h4>
<p><strong>比较常用的是 MyISAM 和 InnoBD</strong></p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th></th>
<th><strong>MyISAM</strong></th>
<th><strong>InnoDB</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>构成上的区别</td>
<td>每个 MyISAM 在磁盘上存储成三个文件。<br />存储表定义文件的扩展名指出文件类型 .frm<br />数据文件的扩展名为 .MYD (MYData)。<br />索引文件的扩展名是 .MYI (MYIndex)。</td>
<td>InnoDB 表基于磁盘的资源存储 <strong>空间数据文件和它的日志文件</strong>，InnoDB 表的大小只受限于操作系统文件的大小，一般为 2GB</td>
</tr>
<tr>
<td>事务处理上方面</td>
<td>MyISAM 类型的表强调的是性能，其执行数度比 InnoDB 类型更快，但是 <strong>不提供事务支持</strong>。</td>
<td>InnoDB 提供事务 <strong>支持事务</strong>，外部键（foreign key）等高级数据库功能</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span><br /><span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span><br /><span style="overflow-x: auto; max-width:100%; display:inline;"><code>INSERT</code></span><br /><span style="overflow-x: auto; max-width:100%; display:inline;"><code>DELETE</code></span></td>
<td>如果执行大量的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span>，MyISAM 是更好的选择。</td>
<td>1. 如果你的数据执行大量的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>INSERT</code></span> 或 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span>，出于性能方面的考虑，应该使用InnoDB 表。<br />2. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>DELETE FROM table</code></span> 时，InnoDB 不会重新建立表，而是一行一行的删除。<br />3. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>LOAD TABLE FROM MASTER</code></span> 操作对 InnoDB 是不起作用的，解决方法是首先把InnoDB 表改成 MyISAM 表，导入数据后再改成 InnoDB 表，但是对于使用的额外的InnoDB 特性（例如外键）的表不适用。</td>
</tr>
<tr>
<td>AUTO_INCREMENT</td>
<td>每表一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMEN</code></span>列的内部处理。<br />MyISAM 为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>INSERT</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span> 操作自动更新这一列。这使得 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 列更快（至少10%）。在序列顶的值被删除之后就不能再利用。(当<span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 列被定义为多列索引的最后一列，可以出现重使用从序列顶部删除的值的情况）。<br /><span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 值可用<span style="overflow-x: auto; max-width:100%; display:inline;"><code>ALTER TABLE</code></span> 或 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>myisamch</code></span> 来重置。<br />对于 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 类型的字段，InnoDB 中必须包含只有该字段的索引，但是在MyISAM 表中，可以和其他字段一起建立联合索引。<br />更好和更快的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 处理。</td>
<td>如果你为一个表指定<span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 列，在数据词典里的 InnoDB 表句柄包含一个名为自动增长计数器的计数器，它被用在为该列赋新值。<br />自动增长计数器仅被存储在主内存中，而不是存在磁盘上。<br />关于该计算器的算法实现，请参考 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AUTO_INCREMENT</code></span> 列在 InnoDB 里如何工作。</td>
</tr>
<tr>
<td>表的具体行数</td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>select count(*) from table</code></span><br />MyISAM 只要简单的读出保存好的行数，注意的是，当 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>count(*)</code></span> 语句包含 where 条件时，两种表的操作是一样的。</td>
<td>InnoDB 中不保存表的具体行数，也就是说，执行 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>select count(*) from table</code></span> 时，InnoDB 要扫描一遍整个表来计算有多少行。</td>
</tr>
<tr>
<td>锁</td>
<td><strong>表锁</strong></td>
<td>提供 <strong>行锁</strong> (locking on row level)，提供与 Oracle 类型一致的不加锁读取 (non-locking read in SELECTs)，另外，InnoDB 表的行锁也不是绝对的，如果在执行一个SQL 语句时 MySQL 不能确定要扫描的范围，InnoDB 表同样会锁全表，例如 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>update table set num=1 where name like "%aaa%"</code></span></td>
</tr>
</tbody>
</table></div>
<p><strong>MySQL 存储引擎 MyISAM 与 InnoDB 如何选择？</strong></p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th></th>
<th>MyISAM</th>
<th>InnoDB</th>
</tr>
</thead>
<tbody>
<tr>
<td>事务</td>
<td>不支持事务</td>
<td>支持事务</td>
</tr>
<tr>
<td>适合应用</td>
<td><strong>查询</strong> 以及 <strong>插入</strong> 为主的应用</td>
<td><strong>频繁修改</strong> 以及涉及到安全性较高的应用（修改需要调整 B+ 数的结构）</td>
</tr>
<tr>
<td>外键</td>
<td>不支持外键</td>
<td>支持外键</td>
</tr>
<tr>
<td>是否默认引擎</td>
<td>默认引擎</td>
<td></td>
</tr>
<tr>
<td>索引</td>
<td></td>
<td>不支持FULLTEXT 类型的索引</td>
</tr>
<tr>
<td>表的行数</td>
<td>保存表的行数<br />只要简单的读出保存好的行数即可。<br />当 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>count(*)</code></span> 语句包含 where 条件时，也需要扫描整个表。</td>
<td>不保存表的行数<br />需要扫描一遍整个表来计算有多少行。</td>
</tr>
<tr>
<td>自增字段</td>
<td>可以和其他字段一起建立联合索引</td>
<td>必须包含只有该字段的索引</td>
</tr>
<tr>
<td>清空整个表时</td>
<td>重建表</td>
<td>一行一行的删除</td>
</tr>
<tr>
<td>锁</td>
<td>表锁</td>
<td>行锁</td>
</tr>
</tbody>
</table></div>
<p>推荐个人博客系统使用 MyISAM，因为在博客里主要操作是读取和写入，很少有链式操作。所以选择 MyISAM 引擎使你博客打开也页面的效率要高于 InnoDB 引擎的博客。</p>
<h4 id="1272-myisam-533">12.7.2 配置MyISAM 存储引擎 533</h4>
<h4 id="1273-innodb-536">12.7.3 配置InnoDB 存储引擎 536</h4>
<p><strong>InnoDB</strong> 是第一个完整支持 ACID 事务的 mysql 存储引擎，特点是行锁设计，支持 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span>，支持外检，提供 <strong>一致性非锁定读</strong>，同时被设计用来最有效地利用及上使用内存和 cpu。</p>
<p><strong>表空间文件</strong></p>
<p>InnoDB 将所有数据（表数据，索引，插入缓冲索引页，回滚信息，插入缓冲索引页，系统事务信息，二次写缓冲等等）逻辑地放在一个空间中，称为共享表空间。</p>
<h4 id="1274-falcon-541">12.7.4 配置Falcon 存储引擎 541</h4>
<h3 id="128-load-data-local-541">12.8 启用或者禁用LOAD DATA 语句的LOCAL 能力 541</h3>
<h3 id="129-542">12.9 国际化和本地化问题 542</h3>
<h4 id="1291-mysql-542">12.9.1 设置MySQL 服务器的地理时区 542</h4>
<h4 id="1292-544">12.9.2 选择用来显示出错信息的语言 544</h4>
<h4 id="1293-mysql-544">12.9.3 配置MySQL 服务器的字符集支持 544</h4>
<h3 id="1210-545">12.10 运行多个服务器 545</h3>
<h4 id="12101-545">12.10.1 运行多个服务器的问题 545</h4>
<h4 id="12102-547">12.10.2 配置和编译不同的服务器 547</h4>
<h4 id="12103-548">12.10.3 指定启动选项的决策 548</h4>
<h4 id="12104-mysqld_multi-549">12.10.4 用于服务器管理的mysqld_multi 549</h4>
<h4 id="12105-windows-mysql-550">12.10.5 在Windows 系统上运行多个MySQL 服务器 550</h4>
<h3 id="1211-mysql-553">12.11 升 级MySQL 553</h3>
<h2 id="13-555">第13 章 访问控件和安全 555</h2>
<h3 id="131-555">13.1 内部安全性：防止未经授权的文件系统访问 555</h3>
<h4 id="1311-556">13.1.1 如何偷取数据 556</h4>
<h4 id="1312-mysql-557">13.1.2 保护你的MySQL 安装 557</h4>
<h3 id="132-562">13.2 外部安全性：防止未经授权的网络访问 562</h3>
<h4 id="1321-mysql-562">13.2.1 MySQL 权限表的结构和内容 562</h4>
<h4 id="1322-568">13.2.2 服务器如何控制客户访问 568</h4>
<h4 id="1323-572">13.2.3 一个关于权限的难题 572</h4>
<h4 id="1324-575">13.2.4 应该回避的权限数据表风险 575</h4>
<h3 id="133-577">13.3 加密连接的建立 577</h3>
<h2 id="14-mysql-582">第14 章 MySQL 数据库的维护、备份和复制 582</h2>
<h3 id="141-582">14.1 数据库预防性维护工作的基本原则 582</h3>
<h3 id="142-mysql-583">14.2 在MySQL 服务器运行时维护数据库 583</h3>
<h4 id="1421-584">14.2.1 以只读方式或读/写方式锁定一个或多个数据表 584</h4>
<h4 id="1422-586">14.2.2 以只读方式锁定所有的数据库 586</h4>
<h3 id="143-587">14.3 预防性维护 587</h3>
<h4 id="1431-mysql-587">14.3.1 充分利用MySQL 服务器的自动恢复能力 587</h4>
<h4 id="1432-588">14.3.2 定期进行预防性维护 588</h4>
<h3 id="144-589">14.4 制作数据库备份 589</h3>
<h4 id="1441-mysqldump-590">14.4.1 用mysqldump 程序制作文本备份 590</h4>
<h4 id="1442-593">14.4.2 制作二进制数据库备份 593</h4>
<h4 id="1443-innodbfaclcon-595">14.4.3 备份InnoDB或Faclcon数据表 595</h4>
<h3 id="145-596">14.5 把数据库复制到另一个服务器 596</h3>
<h4 id="1451-596">14.5.1 使用一个备份文件来复制数据库 596</h4>
<h4 id="1452-597">14.5.2 把数据库从一个服务器复制到另一个 597</h4>
<h3 id="146-598">14.6 数据表的检查和修复 598</h3>
<h4 id="1461-599">14.6.1 用服务器检查和修复数据表 599</h4>
<h4 id="1462-mysqlcheck-599">14.6.2 用mysqlcheck 程序检查和修复数据表 599</h4>
<h4 id="1463-myisamchk-600">14.6.3 用myisamchk 程序检查和修复数据表 600</h4>
<h3 id="147-603">14.7 使用备份进行数据恢复 603</h3>
<h4 id="1471-603">14.7.1 恢复整个数据库 603</h4>
<h4 id="1472-604">14.7.2 恢复数据表 604</h4>
<h4 id="1473-605">14.7.3 重新执行二进制日志文件里的语句 605</h4>
<h4 id="1474-innodb-606">14.7.4 InnoDB 存储引擎的自动恢复功能 606</h4>
<h3 id="148-607">14.8 设置复制服务器 607</h3>
<h4 id="1481-607">14.8.1 复制机制的工作原理 607</h4>
<h4 id="1482-609">14.8.2 建立主从复制关系 609</h4>
<h4 id="1483-611">14.8.3 二进制日志的格式 611</h4>
<h4 id="1484-612">14.8.4 使用复制机制制作备份 612</h4>
<p>第四部分 附 录<br />
附录A 获得并安装有关软件 614<br />
附录B 数据类型指南 630<br />
附录C 操作符与函数用法指南 643<br />
附录D 系统变量、状态变量和用户变量使用指南 705<br />
附录E SQL 语法指南 746<br />
附录F MySQL 程序指南 823<br />
附录G API 指南（图灵网站下载）<br />
附录H Perl DBI API 指南（图灵网站下载）<br />
附录I PHP API 指南（图灵网站下载）</p>
<blockquote class="content-quote">
<p>以下内容来自于菜鸟教程</p>
</blockquote>
<h2 id="mysql_1">MySQL 教程</h2>
<p>数据库（Database）是按照数据结构来组织、存储和管理数据的仓库。</p>
<p>每个数据库都有一个或多个不同的 API 用于创建，访问，管理，搜索和复制所保存的数据。</p>
<p>我们也可以将数据存储在文件中，但是在文件中读写数据速度相对较慢。</p>
<p>所以，现在我们使用关系型数据库管理系统（RDBMS）来存储和管理大数据量。所谓的关系型数据库，是建立在关系模型基础上的数据库，借助于集合代数等数学概念和方法来处理数据库中的数据。</p>
<p>RDBMS 即关系数据库管理系统(Relational Database Management System)的特点：</p>
<ol>
<li>数据以表格的形式出现</li>
<li>每行为各种记录名称</li>
<li>每列为记录名称所对应的数据域</li>
<li>许多的行和列组成一张表单</li>
<li>若干的表单组成database</li>
</ol>
<h2 id="rdbms">RDBMS 术语</h2>
<p>在我们开始学习MySQL 数据库前，让我们先了解下RDBMS的一些术语：</p>
<ul>
<li><strong>数据库：</strong>数据库是一些关联表的集合。</li>
<li><strong>数据表：</strong> 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。</li>
<li><strong>列：</strong> 一列（数据元素）包含了相同类型的数据, 例如邮政编码的数据。</li>
<li><strong>行：</strong>一行（=元组，或记录）是一组相关的数据，例如一条用户订阅的数据。</li>
<li><strong>冗余：</strong>存储两倍数据，冗余降低了性能，但提高了数据的安全性。</li>
<li><strong>主键：</strong>主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。</li>
<li><strong>外键：</strong>外键用于关联两个表。</li>
<li><strong>复合键</strong>：复合键（组合键）将多个列作为一个索引键，一般用于复合索引。</li>
<li><strong>索引：</strong>使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。</li>
<li><strong>参照完整性：</strong> 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件，目的是保证数据的一致性。</li>
</ul>
<h3 id="mysql_2">MySQL</h3>
<p>MySQL 为 <strong>关系型数据库</strong>（Relational Database Management System），这种所谓的&rdquo;关系型&rdquo;可以理解为&rdquo;表格&rdquo;的概念，一个关系型数据库由一个或数个表格组成。</p>
<p>MySQL 是一个关系型数据库管理系统，由瑞典 MySQL AB 公司开发，目前属于 Oracle 公司。MySQL 是一种关联数据库管理系统，<strong>关联数据库将数据保存在不同的表中，而不是将所有数据放在一个大仓库内，这样就增加了速度并提高了灵活性。</strong></p>
<ul>
<li>MySQL 是开源的，目前隶属于 Oracle 旗下产品。</li>
<li>MySQL 支持大型的数据库。可以处理拥有上千万条记录的大型数据库。</li>
<li>MySQL 使用标准的 SQL 数据语言形式。</li>
<li>MySQL 可以运行于多个系统上，并且支持多种语言。这些编程语言包括 C、C++、Python、Java、Perl、PHP、Eiffel、Ruby 和 Tcl 等。</li>
<li>MySQL 支持大型数据库，支持 5000 万条记录的数据仓库，32 位系统表文件最大可支持 4GB，64 位系统支持最大的表文件为8TB。</li>
<li>MySQL 是可以定制的，采用了 GPL 协议，你可以修改源码来开发自己的 MySQL 系统。</li>
</ul>
<h4 id="_1">表格的基本内容：</h4>
<ul>
<li>表头（header）：每一列的名称;</li>
<li>列（col）：具有相同数据类型的数据的集合;</li>
<li>行（row）：每一行用来描述某条记录的具体信息;</li>
<li>值（value）：行的具体信息, 每个值必须与该列的数据类型相同;</li>
<li><strong>键（key)</strong>：键的值在当前列中具有唯一性。</li>
</ul>
<h3 id="nosql">NoSQL</h3>
<p>NoSQL 泛指非关系型的数据库。NoSQL仅仅是一个概念，泛指非关系型的数据库，区别于关系数据库，它们不保证关系数据的ACID特性。</p>
<p>有如下优点：</p>
<ul>
<li><strong>易扩展</strong>，NoSQL数据库种类繁多，但是一个共同的特点都是 <strong>去掉关系数据库的关系型特性</strong>。数据之间无关系，这样就非常容易扩展。无形之间也在架构的层面上带来了可扩展的能力。</li>
<li><strong>大数据量，高性能</strong>，NoSQL数据库都具有非常高的读写性能，尤其在大数据量下，同样表现优秀。这得益于它的无关系性，数据库的结构简单。</li>
<li><strong>灵活的数据模型</strong>，NoSQL无须事先为要存储的数据建立字段，随时可以存储自定义的数据格式。而在关系数据库里，增删字段是一件非常麻烦的事情。如果是非常大数据量的表，增加字段简直就是——个噩梦。</li>
<li><strong>高可用</strong>，NoSQL在不太影响性能的情况，就可以方便地实现高可用的架构。</li>
</ul>
<p><strong>接下来我们需要配置下 MySQL 的配置文件</strong></p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">[client]
default-character-set=utf8      # 设置mysql客户端默认字符集

[mysqld]
port = 3306                     # 设置3306端口
basedir=                        # 设置mysql的安装目录
max_connections=20              # 允许最大连接数
character-set-server=utf8       # 服务端使用的字符集默认为8比特编码的latin1字符集
default-storage-engine=INNODB   # 创建新表时将使用的默认存储引擎
</code></span></code></pre>
<h2 id="mysql_3">登录 MySQL</h2>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">mysql -h 主机名 -u 用户名 -p
</code></span></code></pre>
<ul>
<li><strong>-h</strong> : 指定客户端所要登录的 MySQL 主机名, 登录本机（localhost 或 127.0.0.1）该参数可以省略;</li>
<li><strong>-u</strong> : 登录的用户名;</li>
<li><strong>-p</strong> : 告诉服务器将会使用一个密码来登录, 如果所要登录的用户名密码为空, 可以忽略此选项。</li>
</ul>
<p>如果我们要登录本机的 MySQL 数据库，只需要输入以下命令即可：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">mysql -u root -p
</code></span></code></pre>
<h2 id="mysql_4">MySQL 的启动和关闭</h2>
<h3 id="linux">Linux</h3>
<p>首先，我们需要通过以下命令来检查MySQL服务器是否启动：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">ps -ef | grep mysqld
</code></span></code></pre>
<h4 id="_2">启动服务</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">service mysql start
</code></span></code></pre>
<h4 id="_3">关闭服务</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">service mysql stop
</code></span></code></pre>
<h4 id="_4">重启服务</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-shell">service restart stop
</code></span></code></pre>
<blockquote class="content-quote">
<p>https://blog.csdn.net/weixin_45793065/article/details/106574616</p>
<p>```shell<br />
✘ zromyk@centos ~ $ systemctl start mysqld<br />
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===<br />
Authentication is required to manage system services or units.<br />
Authenticating as: root<br />
Password: <br />
polkit-agent-helper-1: pam_authenticate failed: Authentication failure<br />
==== AUTHENTICATION FAILED ===<br />
Failed to start mysqld.service: Access denied<br />
See system logs and &lsquo;systemctl status mysqld.service&rsquo; for details.</p>
<h1 id="service-mysql-start-binsystemctl-restart-mysqlservice">原因推测：service mysql start 是重定向到/bin/systemctl restart mysql.service.</h1>
<h1 id="mysqlmysqldmysqld">mysql与mysqld是不同的，前者交互式命令（客户端），mysqld才是后端服务进程</h1>
<h1 id="_5">使用下面命令即可：</h1>
<p>✘ zromyk@centos ~ $ sudo systemctl start mysqld<br />
```</p>
<p>启动 MySQL：</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>shell
sudo systemctl start mysqld</code></span></p>
<p>查看 MySQL 运行状态：</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>shell
sudo systemctl status mysqld</code></span></p>
</blockquote>
<h2 id="mysql_5">管理 MySQL 的命令</h2>
<h3 id="show-databases"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW DATABASES;</code></span></h3>
<p>列出 MySQL 数据库管理系统的数据库列表。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)
</code></span></code></pre>
<h3 id="use"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>USE [数据库名];</code></span></h3>
<p>选择要操作的 Mysql 数据库，使用该命令后所有 Mysql 命令都只针对该数据库。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; use `mysql`;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
</code></span></code></pre>
<h3 id="show-tables"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW TABLES;</code></span></h3>
<p>显示指定数据库的所有表，使用该命令前需要使用 use 命令来选择要操作的数据库。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; show tables;
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| columns_priv              |
| db                        |
-- ... 本演示中已隐藏
| time_zone_transition_type |
| user                      |
+---------------------------+
31 rows in set (0.00 sec)
</code></span></code></pre>
<h3 id="show-columns-from"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW COLUMNS FROM [数据表];</code></span></h3>
<p>显示数据表的属性，属性类型，主键信息 ，是否为 NULL，默认值等其他信息。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; show columns from `user`;
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Field                  | Type                              | Null | Key | Default               | Extra |
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
| Host                   | char(60)                          | NO   | PRI |                       |       |
| User                   | char(32)                          | NO   | PRI |                       |       |
| Select_priv            | enum('N','Y')                     | NO   |     | N                     |       |
-- ... 本演示中已隐藏
| password_lifetime      | smallint(5) unsigned              | YES  |     | NULL                  |       |
| account_locked         | enum('N','Y')                     | NO   |     | N                     |       |
+------------------------+-----------------------------------+------+-----+-----------------------+-------+
45 rows in set (0.00 sec)
</code></span></code></pre>
<h3 id="show-index-from"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>SHOW INDEX FROM [数据表];</code></span></h3>
<p>显示数据表的详细索引信息，包括PRIMARY KEY（主键）。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; show index from `user`;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY  |            1 | Host        | A         |        NULL |     NULL | NULL   |      | BTREE      |         |               |
| user  |          0 | PRIMARY  |            2 | User        | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
</code></span></code></pre>
<h2 id="mysql_6">MySQL 数据库操作</h2>
<h3 id="create-database"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>CREATE DATABASE [数据库名];</code></span></h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; create database `数据库名`;
</code></span></code></pre>
<h3 id="drop-database"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>DROP DATABASE [数据库名];</code></span></h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; drop database `数据库名`;
</code></span></code></pre>
<h3 id="use_1"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>USE [数据库名];</code></span></h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; use `数据库名`;
</code></span></code></pre>
<h2 id="mysql_7">MySQL 数据表操作</h2>
<p>创建MySQL数据表需要以下信息：</p>
<ul>
<li>表名</li>
<li>表字段名</li>
<li>定义每个表字段</li>
</ul>
<h3 id="create-table-tablename-columnname-column_type">CREATE TABLE table<em>name (column</em>name column_type);</h3>
<p>以下例子中我们将在 RUNOOB 数据库中创建数据表 runoob_tbl：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; CREATE TABLE IF NOT EXISTS `runoob_tbl`(
   -&gt; `runoob_id` INT NOT NULL AUTO_INCREMENT, -- AUTO_INCREMENT 定义列为自增的属性，一般用于主键，数值会自动加1。
   -&gt; `runoob_title` VARCHAR(100) NOT NULL,
   -&gt; `runoob_author` VARCHAR(40) NOT NULL,
   -&gt; `submission_date` DATE,
   -&gt; PRIMARY KEY ( `runoob_id` ) -- PRIMARY KEY 关键字用于定义列为主键。
   -&gt; )ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ENGINE 设置存储引擎，CHARSET 设置编码。
Query OK, 0 rows affected (0.16 sec)
mysql&gt;
</code></span></code></pre>
<p>实例解析：</p>
<ul>
<li>如果你不想字段为 <strong>NULL</strong> 可以设置字段的属性为 <strong>NOT NULL</strong>， 在操作数据库时如果输入该字段的数据为 <strong>NULL</strong> ，就会报错。</li>
<li>AUTO_INCREMENT 定义列为自增的属性，一般用于主键，数值会自动加1。</li>
<li>PRIMARY KEY 关键字用于定义列为主键。 您可以使用多列来定义主键，列间以逗号分隔。</li>
<li>ENGINE 设置存储引擎，CHARSET 设置编码。</li>
</ul>
<h3 id="drop-table-table_name">DROP TABLE table_name;</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; DROP TABLE `runoob_tbl`
Query OK, 0 rows affected (0.8 sec)
mysql&gt;
</code></span></code></pre>
<h3 id="insert-into-table_name-values">INSERT INTO table_name (&hellip;) VALUES (&hellip;)</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">INSERT INTO table_name ( field1, field2,...fieldN )
                       VALUES
                       ( value1, value2,...valueN );
</code></span></code></pre>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; INSERT INTO `runoob_tbl`
    -&gt; (`runoob_title`, `runoob_author`, `submission_date`)
    -&gt; VALUES
    -&gt; (&quot;学习 PHP&quot;, &quot;菜鸟教程&quot;, NOW());
Query OK, 1 rows affected, 1 warnings (0.01 sec)
mysql&gt; INSERT INTO `runoob_tbl`
    -&gt; (`runoob_title`, `runoob_author`, `submission_date`)
    -&gt; VALUES
    -&gt; (&quot;学习 MySQL&quot;, &quot;菜鸟教程&quot;, NOW());
Query OK, 1 rows affected, 1 warnings (0.01 sec)
mysql&gt; INSERT INTO `runoob_tbl`
    -&gt; (`runoob_title`, `runoob_author`, `submission_date`)
    -&gt; VALUES
    -&gt; (&quot;JAVA 教程&quot;, &quot;RUNOOB.COM&quot;, '2016-05-06');
Query OK, 1 rows affected (0.00 sec)
mysql&gt;
</code></span></code></pre>
<h3 id="select">SELECT</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT column_name, column_name FROM table_name
[WHERE Clause]
[LIMIT N][OFFSET M]
</code></span></code></pre>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT field1, field2,...fieldN FROM table_name1, table_name2...
[WHERE condition1 [AND [OR]] condition2.....
</code></span></code></pre>
<ul>
<li>查询语句中你可以使用一个或者多个表，表之间使用逗号<strong><span style="overflow-x: auto; max-width:100%; display:inline;"><code>,</code></span></strong> 分割，并使用WHERE语句来设定查询条件。</li>
<li>你可以在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>WHERE</code></span> 子句中指定任何条件。</li>
<li>你可以使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AND</code></span> 或者 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>OR</code></span> 指定一个或多个条件。</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>WHERE</code></span> 子句也可以运用于 SQL 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>DELETE</code></span> 或者 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span> 命令。</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>WHERE</code></span> 子句类似于程序语言中的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>if</code></span> 条件，根据 MySQL 表中的字段值来读取指定的数据。</li>
</ul>
<p>以下为操作符列表，可用于 WHERE 子句中。</p>
<p>下表中实例假定 A 为 10, B 为 20</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th align="left">操作符</th>
<th align="left">描述</th>
<th align="left">实例</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">=</td>
<td align="left">等号，检测两个值是否相等，如果相等返回true</td>
<td align="left">(A = B) 返回false。</td>
</tr>
<tr>
<td align="left">&lt;&gt;, !=</td>
<td align="left">不等于，检测两个值是否相等，如果不相等返回true</td>
<td align="left">(A != B) 返回 true。</td>
</tr>
<tr>
<td align="left">&gt;</td>
<td align="left">大于号，检测左边的值是否大于右边的值, 如果左边的值大于右边的值返回true</td>
<td align="left">(A &gt; B) 返回false。</td>
</tr>
<tr>
<td align="left">&lt;</td>
<td align="left">小于号，检测左边的值是否小于右边的值, 如果左边的值小于右边的值返回true</td>
<td align="left">(A &lt; B) 返回 true。</td>
</tr>
<tr>
<td align="left">&gt;=</td>
<td align="left">大于等于号，检测左边的值是否大于或等于右边的值, 如果左边的值大于或等于右边的值返回true</td>
<td align="left">(A &gt;= B) 返回false。</td>
</tr>
<tr>
<td align="left">&lt;=</td>
<td align="left">小于等于号，检测左边的值是否小于或等于右边的值, 如果左边的值小于或等于右边的值返回true</td>
<td align="left">(A &lt;= B) 返回 true。</td>
</tr>
</tbody>
</table></div>
<ul>
<li>如果我们想在 MySQL 数据表中读取指定的数据，WHERE 子句是非常有用的。</li>
<li>使用主键来作为 WHERE 子句的条件查询是非常快速的。</li>
<li>如果给定的条件在表中没有任何匹配的记录，那么查询不会返回任何数据。</li>
</ul>
<p>几个示例：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; select * from runoob_tbl;
mysql&gt; SELECT * from runoob_tbl WHERE runoob_author='菜鸟教程';
</code></span></code></pre>
<p>MySQL 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>WHERE</code></span> 子句的字符串比较是不区分大小写的。 你可以使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>BINARY</code></span> 关键字来设定 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>WHERE</code></span> 子句的字符串比较是区分大小写的。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT * from runoob_tbl WHERE BINARY runoob_author='runoob.com';
Empty set (0.01 sec)

mysql&gt; SELECT * from runoob_tbl WHERE BINARY runoob_author='RUNOOB.COM';
-- ...
2 rows in set (0.01 sec)
</code></span></code></pre>
<h3 id="update">UPDATE</h3>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span> 命令修改 MySQL 数据表数据的通用 SQL 语法：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]
</code></span></code></pre>
<ul>
<li>你可以同时更新一个或多个字段。</li>
<li>你可以在 WHERE 子句中指定任何条件。</li>
<li>你可以在一个单独表中同时更新数据。</li>
</ul>
<p><strong>实例</strong></p>
<p>以下实例将更新数据表中 runoob<em>id 为 3 的 runoob</em>title 字段值：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; UPDATE runoob_tbl SET runoob_title='Learn C++' WHERE runoob_id=3;
Query OK, 1 rows affected (0.01 sec)

mysql&gt; SELECT * from runoob_tbl WHERE runoob_id=3;
+-----------+--------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+--------------+---------------+-----------------+
| 3         | Learn C++    | RUNOOB.COM    | 2016-05-06      |
+-----------+--------------+---------------+-----------------+
1 rows in set (0.01 sec)
-- 从结果上看，runoob_id 为 3 的 runoob_title 已被修改。
</code></span></code></pre>
<h3 id="delete">DELETE</h3>
<p>以下是 SQL DELETE 语句从 MySQL 数据表中删除数据的通用语法：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">DELETE FROM table_name [WHERE Clause]
</code></span></code></pre>
<ul>
<li>如果没有指定 WHERE 子句，MySQL 表中的所有记录将被删除。</li>
<li>你可以在 WHERE 子句中指定任何条件</li>
<li>您可以在单个表中一次性删除记录。</li>
</ul>
<p><strong>实例</strong></p>
<p>以下实例将删除 runoob<em>tbl 表中 runoob</em>id 为3 的记录：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; DELETE FROM runoob_tbl WHERE runoob_id=3;
Query OK, 1 row affected (0.23 sec)
</code></span></code></pre>
<h3 id="like">LIKE</h3>
<p>以下是 SQL SELECT 语句使用 LIKE 子句从数据表中读取数据的通用语法：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT field1, field2,...fieldN 
FROM table_name
WHERE field1 LIKE condition1 [AND [OR]] filed2 = 'somevalue'
</code></span></code></pre>
<ul>
<li>你可以在 WHERE 子句中指定任何条件。</li>
<li>你可以在 WHERE 子句中使用LIKE子句。</li>
<li>你可以使用LIKE子句代替等号 <strong>=</strong>。</li>
<li>LIKE 通常与 <strong>%</strong> 一同使用，类似于一个元字符的搜索。</li>
<li>你可以使用 AND 或者 OR 指定一个或多个条件。</li>
<li>你可以在 DELETE 或 UPDATE 命令中使用 WHERE&hellip;LIKE 子句来指定条件。</li>
</ul>
<p><strong>实例</strong></p>
<p>以下我们将在 SQL SELECT 命令中使用 WHERE&hellip;LIKE 子句来从MySQL数据表 runoob_tbl 中读取数据。</p>
<p>以下是我们将 runoob<em>tbl 表中获取 runoob</em>author 字段中以 <strong>COM</strong> 为结尾的的所有记录：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT * from runoob_tbl  WHERE runoob_author LIKE '%COM';
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 3         | Learn Java    | RUNOOB.COM    | 2015-05-01      |
| 4         | Learn Python  | RUNOOB.COM    | 2016-03-06      |
+-----------+---------------+---------------+-----------------+
2 rows in set (0.01 sec)
</code></span></code></pre>
<h3 id="union">UNION</h3>
<p>MySQL <span style="overflow-x: auto; max-width:100%; display:inline;"><code>UNION</code></span> 操作符用于连接两个以上的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 语句的结果组合到一个结果集合中。多个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 语句会删除重复的数据。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions]
UNION [ALL | DISTINCT]
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions];
</code></span></code></pre>
<ul>
<li><strong>expression1, expression2, &hellip; expression_n</strong>: 要检索的列。</li>
<li><strong>tables:</strong> 要检索的数据表。</li>
<li><strong>WHERE conditions:</strong> 可选， 检索条件。</li>
<li><strong>DISTINCT:</strong> 可选，删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据，所以 DISTINCT 修饰符对结果没啥影响。</li>
<li><strong>ALL:</strong> 可选，返回所有结果集，包含重复数据。</li>
</ul>
<p><strong>SQL UNION 实例</strong></p>
<p>下面的 SQL 语句从 &ldquo;Websites&rdquo; 和 &ldquo;apps&rdquo; 表中选取所有<strong>不同的</strong>country（只有不同的值）：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT * FROM Websites;
+----+---------------+---------------------------+-------+---------+
| id | name          | url                       | alexa | country |
+----+---------------+---------------------------+-------+---------+
| 1  | Google        | https://www.google.cm/    | 1     | USA     |
| 2  | taobao        | https://www.taobao.com/   | 13    | CN      |
| 3  | runoob        | http://www.runoob.com/    | 4689  | CN      |
| 4  | weibo         | http://weibo.com/         | 20    | CN      |
| 5  | Facebook      | https://www.facebook.com/ | 3     | USA     |
| 7  | stackoverflow | http://stackoverflow.com/ | 0     | IND     |
+----+---------------+---------------------------+-------+---------+
7 rows in set (0.00 sec)

mysql&gt; SELECT * FROM apps;
+----+------------+-------------------------+---------+
| id | app_name   | url                     | country |
+----+------------+-------------------------+---------+
|  1 | QQ APP     | http://im.qq.com/       | CN      |
|  2 | weibo APP  | http://weibo.com/       | CN      |
|  3 | taobao APP | https://www.taobao.com/ | CN      |
+----+------------+-------------------------+---------+
3 rows in set (0.00 sec)

mysql&gt; SELECT country FROM Websites
    -&gt; UNION
    -&gt; SELECT country FROM apps
    -&gt; ORDER BY country;
+---------+
| country |
+---------+
| CN      |
| IND     |
| USA     |
+---------+
3 rows in set (0.00 sec)
</code></span></code></pre>
<h3 id="mysql_8">MySQL 排序</h3>
<p>以下是 SQL SELECT 语句使用 ORDER BY 子句将查询数据排序后再返回数据：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT field1, field2,...fieldN FROM table_name1, table_name2...
ORDER BY field1 [ASC [DESC][默认 ASC]], [field2...] [ASC [DESC][默认 ASC]]
</code></span></code></pre>
<ul>
<li>你可以使用任何字段来作为排序的条件，从而返回排序后的查询结果。</li>
<li>你可以设定多个字段来排序。</li>
<li>你可以使用 <strong><span style="overflow-x: auto; max-width:100%; display:inline;"><code>ASC</code></span></strong> 或 <strong><span style="overflow-x: auto; max-width:100%; display:inline;"><code>DESC</code></span></strong> 关键字来设置查询结果是按 <strong>升序</strong> 或 <strong>降序</strong> 排列。 默认情况下，它是按升序排列。</li>
<li>你可以添加 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>WHERE...LIKE</code></span> 子句来设置条件。</li>
</ul>
<p><strong>实例</strong></p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT * from runoob_tbl ORDER BY submission_date ASC;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 3         | Learn Java    | RUNOOB.COM    | 2015-05-01      |
| 4         | Learn Python  | RUNOOB.COM    | 2016-03-06      |
| 1         | Learn PHP     | RUNOOB.COM    | 2017-04-12      |
| 2         | Learn MySQL   | RUNOOB.COM    | 2017-04-12      |
+-----------+---------------+---------------+-----------------+
4 rows in set (0.01 sec)
</code></span></code></pre>
<h3 id="mysql-group-by">MySQL GROUP BY 语句</h3>
<p>GROUP BY 语句根据一个或多个列对结果集进行分组。</p>
<p>在分组的列上我们可以使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>COUNT</code></span>, <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SUM</code></span>, <span style="overflow-x: auto; max-width:100%; display:inline;"><code>AVG</code></span>,等函数。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
</code></span></code></pre>
<p><strong>实例</strong></p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT * FROM employee_tbl;
+----+--------+---------------------+--------+
| id | name   | date                | singin |
+----+--------+---------------------+--------+
|  1 | 小明   | 2016-04-22 15:25:33 |      1 |
|  2 | 小王   | 2016-04-20 15:25:47 |      3 |
|  3 | 小丽   | 2016-04-19 15:26:02 |      2 |
|  4 | 小王   | 2016-04-07 15:26:14 |      4 |
|  5 | 小明   | 2016-04-11 15:26:40 |      4 |
|  6 | 小明   | 2016-04-04 15:26:54 |      2 |
+----+--------+---------------------+--------+
6 rows in set (0.00 sec)
</code></span></code></pre>
<p>接下来我们使用 GROUP BY 语句 将数据表按名字进行分组，并统计每个人有多少条记录：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT name, COUNT(*) FROM employee_tbl GROUP BY name;
+--------+----------+
| name   | COUNT(*) |
+--------+----------+
| 小丽   |        1 |
| 小明   |        3 |
| 小王   |        2 |
+--------+----------+
3 rows in set (0.01 sec)
</code></span></code></pre>
<p><strong>使用 WITH ROLLUP</strong></p>
<p>WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计（SUM, AVG, COUNT…）。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">mysql&gt; SELECT name, SUM(singin) as singin_count 
    -&gt; FROM employee_tbl GROUP BY name WITH ROLLUP;
+--------+--------------+
| name   | singin_count |
+--------+--------------+
| 小丽   |            2 |
| 小明   |            7 |
| 小王   |            7 |
| NULL   |           16 | -- 其中记录 NULL 表示所有人的登录次数。
+--------+--------------+
4 rows in set (0.00 sec)
</code></span></code></pre>
<p>我们可以使用 coalesce 来设置一个可以取代 NULL 的名称，coalesce 语法：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">SELECT coalesce(a,b,c);
</code></span></code></pre>
<p>参数说明：</p>
<p>如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>a != null</code></span>，则选择a；</p>
<p>如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>a == null</code></span>，则选择b；</p>
<p>如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>b == null</code></span>，则选择c；</p>
<p>如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>a b c</code></span> 都为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>null</code></span> ，则返回为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>null</code></span>（没意义）。</p>
<p>以下实例中如果名字为空我们使用总数代替：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-mysql">-- 如果 name == null 则显示为 总数
mysql&gt; SELECT coalesce(name, '总数'), SUM(singin) as singin_count 
    -&gt; FROM  employee_tbl GROUP BY name WITH ROLLUP;
+--------------------------+--------------+
| coalesce(name, '总数')    | singin_count |
+--------------------------+--------------+
| 小丽                      |            2 |
| 小明                      |            7 |
| 小王                      |            7 |
| 总数                      |           16 |
+--------------------------+--------------+
4 rows in set (0.01 sec)
</code></span></code></pre>
<h3 id="mysql_9">MySQL 连接的使用</h3>
<blockquote class="content-quote">
<p>待续&hellip;，转自：<a href="https://www.runoob.com/mysql/mysql-join.html">MySQL 菜鸟教程：https://www.runoob.com/mysql/mysql-join.html</a></p>
</blockquote>
<h2 id="mysql_10">MySQL 数据类型</h2>
<h4 id="_6">数值类型</h4>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th align="left">类型</th>
<th align="left">大小</th>
<th align="left">范围（有符号）</th>
<th align="left">范围（无符号）</th>
<th align="left">用途</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">TINYINT</td>
<td align="left">1 byte</td>
<td align="left">(-128，127)</td>
<td align="left">(0，255)</td>
<td align="left">小整数值</td>
</tr>
<tr>
<td align="left">SMALLINT</td>
<td align="left">2 bytes</td>
<td align="left">(-32 768，32 767)</td>
<td align="left">(0，65 535)</td>
<td align="left">大整数值</td>
</tr>
<tr>
<td align="left">MEDIUMINT</td>
<td align="left">3 bytes</td>
<td align="left">(-8 388 608，8 388 607)</td>
<td align="left">(0，16 777 215)</td>
<td align="left">大整数值</td>
</tr>
<tr>
<td align="left">INT或INTEGER</td>
<td align="left">4 bytes</td>
<td align="left">(-2 147 483 648，2 147 483 647)</td>
<td align="left">(0，4 294 967 295)</td>
<td align="left">大整数值</td>
</tr>
<tr>
<td align="left">BIGINT</td>
<td align="left">8 bytes</td>
<td align="left">(-9,223,372,036,854,775,808，9 223 372 036 854 775 807)</td>
<td align="left">(0，18 446 744 073 709 551 615)</td>
<td align="left">极大整数值</td>
</tr>
<tr>
<td align="left">FLOAT</td>
<td align="left">4 bytes</td>
<td align="left">(-3.402 823 466 E+38，-1.175 494 351 E-38)，0，(1.175 494 351 E-38，3.402 823 466 351 E+38)</td>
<td align="left">0，(1.175 494 351 E-38，3.402 823 466 E+38)</td>
<td align="left">单精度 浮点数值</td>
</tr>
<tr>
<td align="left">DOUBLE</td>
<td align="left">8 bytes</td>
<td align="left">(-1.797 693 134 862 315 7 E+308，-2.225 073 858 507 201 4 E-308)，0，(2.225 073 858 507 201 4 E-308，1.797 693 134 862 315 7 E+308)</td>
<td align="left">0，(2.225 073 858 507 201 4 E-308，1.797 693 134 862 315 7 E+308)</td>
<td align="left">双精度 浮点数值</td>
</tr>
<tr>
<td align="left">DECIMAL</td>
<td align="left">DECIMAL(M,D) ，如果M&gt;D，为M+2否则为D+2</td>
<td align="left">依赖于M和D的值</td>
<td align="left">依赖于M和D的值</td>
<td align="left">小数值</td>
</tr>
</tbody>
</table></div>
<h4 id="_7">日期和时间类型</h4>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th align="left">类型</th>
<th align="left">大小 ( bytes)</th>
<th align="left">范围</th>
<th align="left">格式</th>
<th align="left">用途</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">DATE</td>
<td align="left">3</td>
<td align="left">1000-01-01/9999-12-31</td>
<td align="left">YYYY-MM-DD</td>
<td align="left">日期值</td>
</tr>
<tr>
<td align="left">TIME</td>
<td align="left">3</td>
<td align="left">&lsquo;-838:59:59&rsquo;/&lsquo;838:59:59&rsquo;</td>
<td align="left">HH:MM:SS</td>
<td align="left">时间值或持续时间</td>
</tr>
<tr>
<td align="left">YEAR</td>
<td align="left">1</td>
<td align="left">1901/2155</td>
<td align="left">YYYY</td>
<td align="left">年份值</td>
</tr>
<tr>
<td align="left">DATETIME</td>
<td align="left">8</td>
<td align="left">1000-01-01 00:00:00/9999-12-31 23:59:59</td>
<td align="left">YYYY-MM-DD HH:MM:SS</td>
<td align="left">混合日期和时间值</td>
</tr>
<tr>
<td align="left">TIMESTAMP</td>
<td align="left">4</td>
<td align="left">1970-01-01 00:00:00/2038 结束时间是第 <strong>2147483647</strong> 秒，北京时间 <strong>2038-1-19 11:14:07</strong>，格林尼治时间 2038年1月19日 凌晨 03:14:07</td>
<td align="left">YYYYMMDD HHMMSS</td>
<td align="left">混合日期和时间值，时间戳</td>
</tr>
</tbody>
</table></div>
<h4 id="_8">字符串(字符)类型</h4>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th align="left">类型</th>
<th align="left">大小</th>
<th align="left">用途</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">CHAR</td>
<td align="left">0-255 bytes</td>
<td align="left">定长字符串</td>
</tr>
<tr>
<td align="left">VARCHAR</td>
<td align="left">0-65535 bytes</td>
<td align="left">变长字符串</td>
</tr>
<tr>
<td align="left">TINYBLOB</td>
<td align="left">0-255 bytes</td>
<td align="left">不超过 255 个字符的二进制字符串</td>
</tr>
<tr>
<td align="left">TINYTEXT</td>
<td align="left">0-255 bytes</td>
<td align="left">短文本字符串</td>
</tr>
<tr>
<td align="left">BLOB</td>
<td align="left">0-65 535 bytes</td>
<td align="left">二进制形式的长文本数据</td>
</tr>
<tr>
<td align="left">TEXT</td>
<td align="left">0-65 535 bytes</td>
<td align="left">长文本数据</td>
</tr>
<tr>
<td align="left">MEDIUMBLOB</td>
<td align="left">0-16 777 215 bytes</td>
<td align="left">二进制形式的中等长度文本数据</td>
</tr>
<tr>
<td align="left">MEDIUMTEXT</td>
<td align="left">0-16 777 215 bytes</td>
<td align="left">中等长度文本数据</td>
</tr>
<tr>
<td align="left">LONGBLOB</td>
<td align="left">0-4 294 967 295 bytes</td>
<td align="left">二进制形式的极大文本数据</td>
</tr>
<tr>
<td align="left">LONGTEXT</td>
<td align="left">0-4 294 967 295 bytes</td>
<td align="left">极大文本数据</td>
</tr>
</tbody>
</table></div>
<h2 id="mvcc">MVCC</h2>
<h3 id="mvcc_1">MVCC 概述</h3>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC (Multiversion Concurrency Control)</code></span> 中文全称叫多版本并发控制，是现代数据库（包括 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MySQL</code></span>、<span style="overflow-x: auto; max-width:100%; display:inline;"><code>Oracle</code></span> 、<span style="overflow-x: auto; max-width:100%; display:inline;"><code>PostgreSQL</code></span> 等）引擎实现中常用的 <strong>处理读写冲突的手段</strong>， 目的在于提高数据库高并发场景下的吞吐性能 。 </p>
<p>不同的事务在并发过程中，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 操作 <strong>可以不加锁</strong> 而是 <strong>通过 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span>机制</strong> 读取指定的版本历史记录，并通过一些手段保证保证读取的记录值符合事务所处的隔离级别，从而解决并发场景下的读写冲突。</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>transaction A</th>
<th>transaction B</th>
</tr>
</thead>
<tbody>
<tr>
<td>select x from table;<br />(return 10)</td>
<td></td>
</tr>
<tr>
<td>begin transaction;</td>
<td></td>
</tr>
<tr>
<td>update table set x = 20;</td>
<td></td>
</tr>
<tr>
<td></td>
<td>begin transaction;</td>
</tr>
<tr>
<td></td>
<td><strong>select x from table;<br />(return rs1)</strong></td>
</tr>
<tr>
<td>commit;</td>
<td></td>
</tr>
<tr>
<td></td>
<td><strong>select x from table;<br />(return rs2)</strong></td>
</tr>
<tr>
<td></td>
<td>commit;</td>
</tr>
</tbody>
</table></div>
<p>事务 B 在不同的隔离级别下，读取到的值不一样。</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>事务 B 的隔离级别</th>
<th>rs1</th>
<th>rs2</th>
</tr>
</thead>
<tbody>
<tr>
<td>读未提交 RU</td>
<td>20</td>
<td>20</td>
</tr>
<tr>
<td>读已提交 RC</td>
<td>10</td>
<td>20</td>
</tr>
<tr>
<td>可重复读 RR</td>
<td>10</td>
<td>10</td>
</tr>
<tr>
<td>串行 S</td>
<td>10</td>
<td>10</td>
</tr>
</tbody>
</table></div>
<p>在不同的隔离级别下，数据库通过 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span> 和隔离级别，让事务之间并行操作遵循了某种规则，来保证单个事务内前后数据的一致性。</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>RC</code></span> 在每一次 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 语句前都会生成一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ReadView</code></span>，事务期间会更新，因此在其他事务提交前后所得到的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>m_ids</code></span> 列表可能发生变化，使得先前不可见的版本后续又突然可见了。而 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>RR</code></span>  只在事务的第一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 语句时生成一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ReadView</code></span>，事务操作期间不更新。</p>
<h3 id="mvcc_2">为什么需要MVCC</h3>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>InnoDB</code></span> 相比 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MyISAM</code></span>  有两大特点：</p>
<ol>
<li>支持事务</li>
<li>支持行级锁</li>
</ol>
<p>事务的引入带来了一些新的挑战。相对于串行处理来说，并发事务处理能大大增加数据库资源的利用率，提高数据库系统的事务吞吐量，从而可以支持可以支持更多的用户。</p>
<p>但并发事务处理也会带来一些问题，主要包括以下几种情况：</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>可能的问题</th>
<th>英文名词</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>更新丢失</td>
<td>Lost Update</td>
<td></td>
</tr>
<tr>
<td>脏读</td>
<td>Dirty Reads</td>
<td>指某个事务所作出的修改在它尚未被提交时就可以被其他事务看到。</td>
</tr>
<tr>
<td>不可重复读</td>
<td>Non-Repeatable Reads</td>
<td>指同一个事务使用同一条 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span> 语句每次读取到的结果不一样。<br />事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span><br />事务二对数据进行了修改<br />事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span></td>
</tr>
<tr>
<td>幻读</td>
<td>Phantom Reads</td>
<td>事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span><br />事务二添加了某些数据<br />事务一<span style="overflow-x: auto; max-width:100%; display:inline;"><code>SELECT</code></span></td>
</tr>
</tbody>
</table></div>
<p>以上是并发事务过程中会存在的问题，解决更新丢失可以交给应用，但是后三者需要数据库提供事务间的隔离机制来解决。  <strong>实现隔离机制的方法主要有两种</strong>：</p>
<ol>
<li>加读写锁</li>
<li>一致性快照读，即 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span></li>
</ol>
<h3 id="innodb-mvcc">InnoDB MVCC实现原理</h3>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>InnoDB</code></span> 中 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span> 的实现方式为：每一行记录都有两个隐藏列：<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DATA_TRX_ID</code></span> 、 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>DATA_ROLL_PTR</code></span>（如果没有主键，则还会多一个隐藏的主键列）。</p>
<p><img class="pure-img" alt="InnoDB MVCC 机制，看这篇就够了" src="/public/download/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/bfa89998d4dea1104d7954d6ab03350e" /></p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>隐藏列</th>
<th>大小</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>DATA<em>TRX</em>ID</td>
<td>6B</td>
<td>记录最近更新这条行记录的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>事务 ID</code></span></td>
</tr>
<tr>
<td>DATA<em>ROLL</em>PTR</td>
<td>7B</td>
<td>表示指向该行回滚段 （<span style="overflow-x: auto; max-width:100%; display:inline;"><code>rollback segment</code></span>）的指针， <span style="overflow-x: auto; max-width:100%; display:inline;"><code>InnoDB</code></span>  便是通过这个指针找到之前版本的数据。该行记录上所有旧版本，在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>undo</code></span>  中都通过链表的形式组织。</td>
</tr>
<tr>
<td>DB<em>ROW</em>ID</td>
<td>6B</td>
<td>行标识（隐藏单调自增 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ID</code></span>），<strong>如果表没有主键， <span style="overflow-x: auto; max-width:100%; display:inline;"><code>InnoDB</code></span>  会自动生成一个隐藏主键，因此会出现这个列。</strong>另外，每条记录的头信息（<span style="overflow-x: auto; max-width:100%; display:inline;"><code>record header</code></span>）里都有一个专门的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bit</code></span>（ <span style="overflow-x: auto; max-width:100%; display:inline;"><code>deleted_flag</code></span>）来表示当前记录是否已经被删除。</td>
</tr>
</tbody>
</table></div>
<h3 id="_9">如何组织版本链</h3>
<p>在多个事务并行操作某行数据的情况下，不同事务对该行数据的 UPDATE 会产生多个版本，然后通过回滚指针组织成一条 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>Undo Log</code></span>  链。</p>
<p><img class="pure-img" alt="InnoDB MVCC 机制，看这篇就够了" src="/public/download/MySQL-%E6%95%B0%E6%8D%AE%E5%BA%93.assets/ab36e68439be8c763c93505d34fcd72c" /></p>
<p>修改操作：</p>
<ol>
<li>对<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DB_ROW_ID = 1</code></span>的这行记录加排他锁。</li>
<li>把该行原本的值拷贝到<span style="overflow-x: auto; max-width:100%; display:inline;"><code>undo log</code></span>中，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DB_TRX_ID</code></span> 和<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DB_ROLL_PTR</code></span> 都不动。</li>
<li>修改该行的值这时产生一个新版本，更新<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DATA_TRX_ID</code></span>为修改记录的事务<span style="overflow-x: auto; max-width:100%; display:inline;"><code>ID</code></span>，将 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>DATA_ROLL_PTR</code></span> 指向刚刚拷贝到<span style="overflow-x: auto; max-width:100%; display:inline;"><code>undo log</code></span> 链中的旧版本记录，这样就能通过<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DB_ROLL_PTR</code></span> 找到这条记录的历史版本。（如果对同一行记录执行连续的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span> ， <span style="overflow-x: auto; max-width:100%; display:inline;"><code>Undo Log</code></span>  会组成一个链表，遍历这个链表可以看到这条记录的变迁。）</li>
<li>记录 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>redo log</code></span> ，包括 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>undo log</code></span>  中的修改。</li>
</ol>
<p>插入操作：</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>INSERT</code></span> 会产生一条新纪录，它的<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DATA_TRX_ID</code></span> 为当前插入记录的事务<span style="overflow-x: auto; max-width:100%; display:inline;"><code>ID</code></span></p>
<p>删除操作：</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>DELETE</code></span> 某条记录时可看成是一种特殊的<span style="overflow-x: auto; max-width:100%; display:inline;"><code>UPDATE</code></span>，其实是软删，真正执行删除操作会在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>commit</code></span> 时，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>DATA_TRX_ID</code></span>则记录下删除该记录的事务<span style="overflow-x: auto; max-width:100%; display:inline;"><code>ID</code></span>。</p>
<h3 id="-readview">如何实现一致性读-ReadView</h3>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>隔离级别</th>
<th>含义</th>
<th>脏读</th>
<th>不可重复读</th>
<th>幻影数据行</th>
</tr>
</thead>
<tbody>
<tr>
<td>Read uncommitted</td>
<td>读未提交</td>
<td>是</td>
<td>是</td>
<td>是</td>
</tr>
<tr>
<td>Read committed</td>
<td>读已提交</td>
<td></td>
<td>是</td>
<td>是</td>
</tr>
<tr>
<td>Repeatable read</td>
<td>可重复读</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Serializable</td>
<td>串行化</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table></div>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>事务 B 的隔离级别</th>
<th></th>
<th>rs1</th>
<th>rs2</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>读未提交 RU</td>
<td>Read uncommitted</td>
<td>20</td>
<td>20</td>
<td>直接读取版本的最新记录就 OK，不需要<span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span>的帮助。</td>
</tr>
<tr>
<td>读已提交 RC</td>
<td>Read committed</td>
<td>10</td>
<td>20</td>
<td></td>
</tr>
<tr>
<td>可重复读 RR</td>
<td>Repeatable read</td>
<td>10</td>
<td>10</td>
<td></td>
</tr>
<tr>
<td>串行 S</td>
<td></td>
<td>10</td>
<td>10</td>
<td>通过加锁互斥来访问数据，不需要<span style="overflow-x: auto; max-width:100%; display:inline;"><code>MVCC</code></span>的帮助。</td>
</tr>
</tbody>
</table></div>
  </div>
</div>
 
    </div>
  </div>
  <div id="footer-background">
    <div id="footer">
      <div class="legal pure-g">
  <div class="pure-u-1 u-sm-1-2">
    <p class="legal-license"><a href="https://beian.miit.gov.cn/#/Integrated/index">浙ICP备2020038748号</a></p>
  </div>
  <div class="pure-u-1 u-sm-1-2">
    <p class="legal-links"><a href="https://github.com/zromyk">GitHub</a></p>
    <p class="legal-copyright">Copyright © 2021 Wei Zhou. 保留所有权利。</p>
  </div>
</div>
    </div>
  </div>
  <!-- <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> -->
  <script src="/style/html/jquery.min.js"></script>
  <script src='/style/article/latex/latest.js?config=TeX-MML-AM_CHTML'></script>
<!-- <script src="https://cdn.geogebra.org/apps/deployggb.js"></script> -->
<script src="/style/article/deployggb.js"></script>
<!-- <script src="https://apps.bdimg.com/libs/highlight.js/9.1.0/highlight.min.js"></script> -->
<script type="text/javascript">
  // 脚本：navigation 随鼠标移动自动变换宽度
  var element = document.getElementById("navigation"); // 获取要操作的元素
  var elementWidth = parseInt(getComputedStyle(element).width);
  var elementLeft = 0;
  var elementRight = 0;
  element.addEventListener('mouseenter', function (event) { // 添加鼠标按下事件的监听器
    elementLeft = element.getBoundingClientRect().left - 10;
    elementRight = element.getBoundingClientRect().left + elementWidth * 3;
    window.addEventListener('mousemove', resize); // 添加全局的鼠标移动事件的监听器
  });

  function resize(event) {
    var minWidth = elementWidth;
    var maxWidth = elementWidth * 2.5;
    // console.log(elementLeft, event.clientX, elementRight, event.clientX - elementLeft + elementWidth / 2);
    if (elementLeft <= event.clientX && event.clientX <= elementRight) {
      var width = event.clientX - elementLeft + elementWidth / 2;
      width = Math.min(width, maxWidth);
      width = Math.max(width, minWidth);
      element.style.width = width + 'px'; // 设置新的宽度样式属性
    }
    else {
      element.style.width = elementWidth + 'px'; // 设置新的宽度样式属性
      stopResize();
    }
  }

  function stopResize() {
    element.style.width = elementWidth + 'px'; // 设置新的宽度样式属性
    // console.log("stopResize", elementLeft, event.clientX, elementRight, event.clientX - elementLeft + elementWidth / 2);
    window.removeEventListener('mousemove', resize); // 移除鼠标移动事件的监听器
  }
</script>
<script src="/style/article/highlight/highlight.min.js"></script>
<script type="text/javascript">
  // 脚本：code语法高亮
  hljs.initHighlightingOnLoad();
</script>
<script>
  function animateByNav() {
    $("html").animate({
        scrollTop: ($(event.target.hash).offset().top - 52)
    }, 300);
  };
</script>
<script src="/style/article/pell-1.0.6/dist/pell.js"></script>
<script>
  // 脚本：自由编辑页面
  var editor = window.pell.init({
    element: document.getElementById('editor'),
    defaultParagraphSeparator: 'p',
    onChange: function(html) {
        document.getElementById('text-output').innerHTML = html
        document.getElementById('html-output').textContent = html
    }
  });

  function markdownEditor() {
    var articles = document.getElementById('content-articles-markdown');
    if (articles.getAttribute("contenteditable") == "true") {
        articles.setAttribute("contenteditable", "false");
        document.getElementById("content-articles-markdownEditor").style.display = "none"; //隐藏
        document.getElementById("button-markdownEditor").innerHTML = "启用编辑";
    } else {
        articles.setAttribute("contenteditable", "true");
        document.getElementById("content-articles-markdownEditor").style.display = ""; //显示
        document.getElementById("button-markdownEditor").innerHTML = "关闭编辑";
    }
  };

  function save() {
      window.alert("保存成功");
  };
</script>

</body>
</html>
